1. Introduction and Aims

We have quality-controlled the 10X data and the SS2 data and now are left with the following objects:

10X 5K data - pb_sex_filtered

10X 30K data - pb_30k_sex_filtered

SS2 mutant data - ss2_mutants_final

2. Read in the data

Load/Install the Required Packages

Read in the Data

screen hits

## EDIT - change this to the excel table once we have it finalized for the screen
screen_hits <- c("PBANKA-0516300",
"PBANKA-1217700",
"PBANKA-0409100",
"PBANKA-1034300",
"PBANKA-1437500",
"PBANKA-0827500",
"PBANKA-0824300",
"PBANKA-1426900",
"PBANKA-0105300",
"PBANKA-0921100",
"PBANKA-1002400",
"PBANKA-0829400",
"PBANKA-1347200",
"PBANKA-0828000",
"PBANKA-0902300",
"PBANKA-1418100",
"PBANKA-1435200",
"PBANKA-1454800",
"PBANKA-0712300",
"PBANKA-0410500",
"PBANKA-1144800",
"PBANKA-1231600",
"PBANKA-0503200",
"PBANKA-0308900",
"PBANKA-1214700",
"PBANKA-0709900",
"PBANKA-0311900",
"PBANKA-0716500",
"PBANKA-1447900",
"PBANKA-0102200",
"PBANKA-0713500",
"PBANKA-0102400",
"PBANKA-1302700",
"PBANKA-1235900",
"PBANKA-0401100",
"PBANKA-0413400",
"PBANKA-1126900",
"PBANKA-1425900",
"PBANKA-0418300",
"PBANKA-1464600",
"PBANKA-0806000")

Read in gene annotations

gene_annotations <- read.table("../data/Reference/GenesByTaxon_Summary.csv", header = TRUE, sep = ",", stringsAsFactors = TRUE)
dim(gene_annotations)

## convert _ to -
gene_annotations$Gene.ID <- gsub("_", "-", gene_annotations$Gene.ID)

load in datasets

paste("10x dataset")
[1] "10x dataset"
pb_sex_filtered
An object of class Seurat 
5098 features across 6191 samples within 1 assay 
Active assay: RNA (5098 features, 2000 variable features)
 2 dimensional reductions calculated: pca, umap
paste("Smart-seq2 dataset")
[1] "Smart-seq2 dataset"
ss2_mutants_final
An object of class Seurat 
5245 features across 2717 samples within 1 assay 
Active assay: RNA (5245 features, 2000 variable features)
 2 dimensional reductions calculated: pca, umap
paste("The composition of the Smart-seq2 dataset is:")
[1] "The composition of the Smart-seq2 dataset is:"
table(ss2_mutants_final@meta.data$genotype)

Mutant     WT 
  2028    689 

3. Merging the Smart-seq2 and 10X Data

Prepare data

tenx_5k_counts_to_integrate
An object of class Seurat 
5098 features across 6191 samples within 1 assay 
Active assay: RNA (5098 features, 0 variable features)

We need to make sure the mutant data is compatible with the 10X data. the 10X data has fewer genes represented so we need to find the intersect of the two before integration.

GCSKO_mutants
An object of class Seurat 
5018 features across 2717 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
## double check that this is the same number of genes
## subset counts so that only genes represented in the other two objects are there:
length(intersect(rownames(tenx_5k_counts), rownames(mutant_counts_for_integration)))
[1] 5018

IMPORTANT - this next step is different to GCSKO_merge as it subsets the smart-seq2 data into wild-type only.

## subset wt on ss2 data:
ss2_wt_cells <- rownames(GCSKO_mutants@meta.data[GCSKO_mutants@meta.data$genotype == "WT", ])
GCSKO_mutants_wtonly <- subset(GCSKO_mutants, cells = ss2_wt_cells)

create list and normalise:

## make list
tenx.justwt.list <- list(tenx_5k_counts_to_integrate, GCSKO_mutants_wtonly)

## prepare data
for (i in 1:length(tenx.justwt.list)) {
    tenx.justwt.list[[i]] <- NormalizeData(tenx.justwt.list[[i]], verbose = FALSE)
    tenx.justwt.list[[i]] <- FindVariableFeatures(tenx.justwt.list[[i]], selection.method = "vst", 
        nfeatures = 2000, verbose = FALSE)
    all.genes <- rownames(tenx.justwt.list[[i]])
    tenx.justwt.list[[i]] <- ScaleData(tenx.justwt.list[[i]], features = all.genes)
}

Integrate objects

## Find anchors
tenx.justwt.anchors <- FindIntegrationAnchors(object.list = tenx.justwt.list, dims = 1:21, verbose = FALSE)

## Integrate data
tenx.justwt.integrated <- IntegrateData(anchorset = tenx.justwt.anchors, dims = 1:21, verbose = FALSE, features.to.integrate = genes_in_tenx_dataset)

4. Dimensionality reduction

PCA

Optimised UMAP

After optimisation, the following UMAP can be calculated:

## Run optimised UMAP
tenx.justwt.integrated <- RunUMAP(tenx.justwt.integrated, reduction = "pca", dims = 1:10, n.neighbors = 50, seed.use = 1234, min.dist = 0.4, repulsion.strength = 0.03, local.connectivity = 150)

Make final plots:


## split seurat object up
ob.list <- SplitObject(tenx.justwt.integrated, split.by = "experiment")

## make plots for each object
plot.list <- lapply(X = ob.list, FUN = function(x) {
    DimPlot(x, dims = c(1,2), pt.size = 1) + theme(legend.position="bottom")
})

composition_umap_10x <- plot.list$`tenx_5k` + 
  coord_fixed() +
  theme_void() +
  scale_color_manual(values=c(replicate(45, "#999999"))) +
  labs(title = paste("10x (wild-type)")) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold"))

composition_umap_ss2 <- plot.list$mutants +
  coord_fixed() +
  theme_void() +
  scale_color_manual(values=c(replicate(46, "#999999"))) +
  labs(title = paste("Smart-seq2 (wild-type)")) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold"))

composition_umap <- composition_umap_10x + composition_umap_ss2 

composition_umap

save

ggsave("../images_to_export/composition_umap.png", plot = composition_umap, device = "png", path = NULL, scale = 1, width = 20, height = 20, units = "cm", dpi = 300, limitsize = TRUE)
## make plots
## hoo dataset correlation
UMAP_hoo <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "Prediction.Spearman.", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("Hoo Predicted Timepoint")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_colour_manual(values = inferno(12))  +
  labs(colour = "hour") +
  theme(legend.position = "bottom", legend.title=element_text(size=10))

## ap2g timecourse in this paper correlation
UMAP_kasia <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "Prediction.Spearman._Kasia", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("AP2G Timecourse Predicted Timepoint")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_colour_manual(values = inferno(10))  +
  labs(colour = "hour") +
  theme(legend.position = "bottom", legend.title=element_text(size=10))

## combine
umap_bulk <- wrap_plots(UMAP_hoo, UMAP_kasia, ncol = 2)

## print
umap_bulk

5. Clustering

Generate clusters

## generate new clusters at low resolution
tenx.justwt.integrated <- FindNeighbors(tenx.justwt.integrated, dims = 1:19, reduction = "pca")
tenx.justwt.integrated <- FindClusters(tenx.justwt.integrated, resolution = 2, random.seed = 42, algorithm = 2)

visualise clusters

DimPlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE, repel = FALSE, label = TRUE)

Make individual plots highlighting where cells in each cluster fall

[1] 24

plot

## this function writes the next bit of code for you
## put it into the console and paste the response
#ploty <- c()
#for(i in seq_along(levels(tenx.justwt.integrated@meta.data$seurat_clusters))){
#  ploty <- paste0(ploty, "list_UMAPs_by_cluster[[", i, "]]", " + ")
#}

## plot
list_UMAPs_by_cluster[[1]] + list_UMAPs_by_cluster[[2]] + list_UMAPs_by_cluster[[3]] + list_UMAPs_by_cluster[[4]] + list_UMAPs_by_cluster[[5]] + list_UMAPs_by_cluster[[6]] + list_UMAPs_by_cluster[[7]] + list_UMAPs_by_cluster[[8]] + list_UMAPs_by_cluster[[9]] + list_UMAPs_by_cluster[[10]] + list_UMAPs_by_cluster[[11]] + list_UMAPs_by_cluster[[12]] + list_UMAPs_by_cluster[[13]] + list_UMAPs_by_cluster[[14]] + list_UMAPs_by_cluster[[15]] + list_UMAPs_by_cluster[[16]] + list_UMAPs_by_cluster[[17]] + list_UMAPs_by_cluster[[18]] + list_UMAPs_by_cluster[[19]] + list_UMAPs_by_cluster[[20]] + list_UMAPs_by_cluster[[21]] + list_UMAPs_by_cluster[[22]] + list_UMAPs_by_cluster[[23]] + list_UMAPs_by_cluster[[24]]

Find Markers

visualise markers

## get the top 10 for each cluster
top10 <- pb.markers %>% group_by(cluster) %>% top_n(n = 10, wt = avg_logFC)

## scale data is missing - but original dfs have scale.data
# df_scaled <- as.matrix(transform(merge(as.data.frame(tenx.justwt.list[[1]]@assays$RNA@scale.data), as.data.frame(tenx.justwt.list[[2]]@assays$RNA@scale.data), by = 0, all=FALSE), row.names=Row.names, Row.names=NULL))
# tenx.justwt.integrated@assays$RNA@scale.data <- df_scaled

## scale data in RNA slot
all.genes <- rownames(tenx.justwt.integrated)
tenx.justwt.integrated <- ScaleData(tenx.justwt.integrated, vars.to.regress = 'experiment', features = all.genes)

## heatmap
DoHeatmap(tenx.justwt.integrated, features = top10$gene) + NoLegend()

6. Define Cluster Identities

Downsampling

# ## check number of cells in each cluster
# df_clusters <- as.data.frame(table(tenx.justwt.integrated@meta.data$integrated_snn_res.2))
# plot(df_clusters)
# 
# ## downsample using appropriate metrics
# tenx.justwt.integrated.downsampled <- subset(tenx.justwt.integrated, downsample = 100)
#   
# ## inspect plot
# FeaturePlot(tenx.justwt.integrated.downsampled, features = "PBANKA-1437500", coord.fixed = TRUE, dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
#   theme_void() + 
#   labs(title = paste("AP2G (Commitment)")) + 
#   theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
#   scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

Marker Genes

useful tools for all plots

## define male and female symbol
female_symbol <- intToUtf8(9792)
male_symbol <- intToUtf8(9794)

## define colour pal
marker_gene_ramp <- colorRampPalette(c("#D3D3D3", "#1D1564"))(50)

Expression - cutoffs - purple


marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1319500", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(ccp2)~(Female))) + 
                          theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=6.0), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, 
                                    features = "PBANKA-0416100", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') +
                        coord_fixed() + 
                        theme_void() + 
                        labs(title = expression(italic(mg1)~(Male))) + 
                        theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                        scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1437500", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(ap2g)~(Commitment))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0831000", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(msp1)~(Schizont))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1102200", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(msp8)~(Asexual))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-1102200 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1101300", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(SBP1)~(Ring))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0722600", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(fam-b2)~(Ring))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0722600 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_HSP70 <- FeaturePlot(tenx.justwt.integrated, 
                                      features = "PBANKA-0711900", 
                                      coord.fixed = TRUE, 
                                      min.cutoff = "q05", 
                                      max.cutoff = "q95", 
                                      dims = c(1,2), 
                                      reduction = "umap", 
                                      pt.size = 0.5, 
                                      order = TRUE, 
                                      slot = 'scale.data') +
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(hsp70)~(Line~Reporter))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0711900 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
# + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)

marker_gene_plot_all

Mutant Genes

Expression - with cutoffs

# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD4 
# PBANKA-0716500        GCSKO-19  MD5 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD3
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_fd3 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-1418100", 
                                   coord.fixed = TRUE,
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                        theme_void() + 
                        labs(title = expression(italic(fd3))) + 
                        theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-1418100 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                        ## add sex symbols
                        #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                        #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md4 <- FeaturePlot(tenx.justwt.integrated, 
                                  dims = c(1,2), 
                                  reduction = "umap", 
                                  features = "PBANKA-0102400", 
                                  coord.fixed = TRUE, 
                                  min.cutoff = "q05",
                                  max.cutoff = "q95", 
                                  pt.size = 0.5, 
                                  order = TRUE, 
                                  slot = 'scale.data') + 
                      theme_void() + 
                      labs(title = expression(italic(md4))) + 
                      theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                      ## add sex symbols
                      #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                      #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md5 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-0716500", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95",
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md5))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = "")) 
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd4 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-1435200", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd4))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = "")) 
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd2 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-0902300", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd2))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       # + annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md3 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-0413400", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95",
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md3))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0413400 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                      #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_gd1 <- FeaturePlot(tenx.justwt.integrated, 
                                  dims = c(1,2), 
                                  reduction = "umap",
                                  features = "PBANKA-0828000", 
                                  coord.fixed = TRUE, 
                                  min.cutoff = "q05", 
                                  max.cutoff = "q95",
                                  pt.size = 0.5, 
                                  order = TRUE, 
                                  slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(gd1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0828000 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md1 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-1302700",
                                    coord.fixed = TRUE,
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md2 <- FeaturePlot(tenx.justwt.integrated,
                                   dims = c(1,2), 
                                   reduction = "umap",
                                   features = "PBANKA-1447900",
                                   coord.fixed = TRUE,
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md2))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd1 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-1454800", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05",
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))
# scale_color_continuous_sequential(palette = "Purples 2")
# scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_gd1 , marker_gene_plot_md1 , marker_gene_plot_md2 , marker_gene_plot_md3 , marker_gene_plot_md4 , marker_gene_plot_md5 , marker_gene_plot_fd1 , marker_gene_plot_fd2 , marker_gene_plot_fd3 , marker_gene_plot_fd4, ncol = 4)
           
## print
mutant_expression_composite

# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD5
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_17 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1418100", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_2 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0102400", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_19 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0716500", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_20 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1435200", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_13 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0902300", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_10 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0413400", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md5")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_3 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0828000", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("gd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_oom <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1302700", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_29 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1447900", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_21 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1454800", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_17 , marker_gene_plot_2 , marker_gene_plot_19 , marker_gene_plot_20 , marker_gene_plot_13 , marker_gene_plot_10 , marker_gene_plot_3 , marker_gene_plot_oom , marker_gene_plot_29 , marker_gene_plot_21 , ncol = 4)
           
## print
mutant_expression_composite

7. Pseudotime on all cells

Pseudotime calculation

save

ggsave("../images_to_export/UMAP_pt_wt.png", plot = umap_pt, device = "png", path = NULL, scale = 1, width = 20, height = 20, units = "cm", dpi = 300, limitsize = TRUE)

gganimnate GIF of pseuodtime

#install.packages("gganimate")
library(gganimate)
#install.packages("gifski")
#install.packages("av")
#library(gifski)
#library(av)

## make dataframe for plotting
## extract data for GGplot version of this
df_animation <- as.data.frame(monocle.object.all@int_colData@listData$reducedDims@listData[["UMAP"]])
## add pt to this data frame:
pt_values <- as.data.frame(pseudotime(monocle.object.all, reduction_method = "UMAP"))
df_animation <- merge(df_animation, pt_values, by="row.names") 
rownames(df_animation) <- df_animation$Row.names
colnames(df_animation)[4] <- "pt"

## make the static plot
p <- ggplot(df_animation, aes(x = UMAP_1, y = UMAP_2, colour = pt)) +
  geom_point() +
  scale_colour_viridis_c(option = "plasma") +
  coord_fixed() +
  theme_void() +
  theme(legend.position = "none")
## view plot
plot(p)

## make animated plot
## make a category for animation
#df_animation$group <- cut(df_animation$pt, 15)

anim <- p +
  transition_time(pt) +
  shadow_mark()

animate(anim, height = 3, width = 3, units = "in", res = 150, bg = 'transparent')

## to change the resolution - https://stackoverflow.com/questions/49058567/define-size-for-gif-created-by-gganimate-change-dimension-resolution 

Save animation

anim_save("animated_UMAP_transparent_bg_wt.gif", path = "../images_to_export/")
## extract pt values
pt_values <- as.data.frame(pseudotime(monocle.object.all, reduction_method = "UMAP"))

tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, pt_values, "old_pt_values")

Define cell identities with branches

Define identities of cells

male

monocle.object_male <- choose_graph_segments(monocle.object.all)

female

monocle.object_female <- choose_graph_segments(monocle.object.all)

bipotential

monocle.object_bipot <- choose_graph_segments(monocle.object.all)

asexual (pre-branch)

monocle.object_asex_pre <- choose_graph_segments(monocle.object.all)

asexual fate

monocle.object_asex_fate <- choose_graph_segments(monocle.object.all)

check

df_freq <- data.frame(table(c(colnames(monocle.object_male), colnames(monocle.object_female), colnames(monocle.object_bipot), colnames(monocle.object_asex_pre), colnames(monocle.object_asex_fate))))
paste("number of cells in seurat object is", length(colnames(monocle.object.all)), ". The number of cells selected here with an identitity is", dim(df_freq)[1])
df_freq <- df_freq[df_freq$Freq > 1, ]
df_freq

Inspect where these missing cells are:

# '%ni%' <- Negate('%in%')
# 
# not_assigned_cells <- colnames(monocle.object.all)[colnames(monocle.object.all) %ni% c(colnames(monocle.object_male), colnames(monocle.object_female), colnames(monocle.object_bipot), colnames(monocle.object_asex), colnames(monocle.object_asex_fate))]
# 
# DimPlot(seurat.object, repel = TRUE, label.size = 5, pt.size = 0.5, cells.highlight = not_assigned_cells, dims = c(2,1), reduction = "DIM_UMAP") +
#   coord_fixed() + 
#   scale_color_manual(values=c("#000000", "#f54e1e"))
## create annotation dataframe from these results:
df_monocle_sexes <- rbind(data.frame("cell_name" = colnames(monocle.object_male), "sex" = rep("Male", length(colnames(monocle.object_male)))),
                          data.frame("cell_name" = colnames(monocle.object_female), "sex" = rep("Female", length(colnames(monocle.object_female)))),
                          data.frame("cell_name" = colnames(monocle.object_bipot), "sex" = rep("Bipotential", length(colnames(monocle.object_bipot)))),
                          data.frame("cell_name" = colnames(monocle.object_asex_pre), "sex" = rep("Asexual_Early", length(colnames(monocle.object_asex_pre)))),
                          data.frame("cell_name" = colnames(monocle.object_asex_fate), "sex" = rep("Asexual_Late", length(colnames(monocle.object_asex_fate))))
                          #data.frame("cell_name" = not_assigned_cells, "sex" = rep("Unassigned", length(not_assigned_cells)))
                          )

dim(df_monocle_sexes)

## order like the metadata
df_monocle_sexes <- df_monocle_sexes[match(rownames(monocle.object.all@colData), df_monocle_sexes$cell_name), ]

## add this back into the monocle object
monocle.object.all@colData$Sexes_monocle <- df_monocle_sexes$sex

## add this to the seurat object
rownames(df_monocle_sexes) <- df_monocle_sexes$cell_name
df_monocle_sexes_to_add_to_seurat <- df_monocle_sexes[,c("sex"), drop = FALSE]
tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, df_monocle_sexes_to_add_to_seurat, col.name = "monocle_sex")

8. Plots

make composite pseudotime/ID figure

save

#ggsave("../images_to_export/umap_id_pt.png", plot = umap_id_pt, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)

cluster plot

umap_with_clusters <- DimPlot(tenx.justwt.integrated,
        group.by = "seurat_clusters_dot_plotting",
        dims = c(1,2), 
        reduction = "umap", 
        pt.size = 1,
        label.box = TRUE,
        label.size = 8,
        label.color = c(rep(c("#000000"), 12), rep(c("#ffffff"), 5), rep(c("#000000"), 2),"#ffffff", "#000000", "#ffffff", "#ffffff"),
        order = TRUE, 
        repel = TRUE, 
        label = TRUE,
        cols = pal_plot) +
  scale_color_manual(labels = c("Asexual 1", "Asexual 2" , "Asexual 3", "Asexual 4", "Asexual 5", "Asexual 6", "Asexual 7", "Asexual 8",  "Asexual 9", "Asexual 10", "Asexual 11", "Asexual 12", "Asexual 13", "Asexual 14", "Asexual 15", "Asexual 16", "Asexual 17", "Bipotential", "Male 1", "Male 2", "Female 1", "Female 2", "Female 3"), values = pal_plot) +
  theme_void() +
                     coord_fixed()
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.

umap_with_clusters

save

ggsave("../images_to_export/umap_with_clusters.png", plot = umap_with_clusters, device = "png", path = NULL, scale = 1, width = 21, height = 29.5, units = "cm", dpi = 300, limitsize = TRUE)

dotplot

A dotplot allows us to look at the expression of multiple genes in a clearer way than succesive UMAP plots

### Data set-up

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0413400    GCSKO-10_820  MD3
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0102400         GCSKO-2  MD5 

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

# PBANKA-1437500 - AP2G - commitment
# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)

marker_genes_list <- c("PBANKA-1437500", "PBANKA-1319500", "PBANKA-0416100", "PBANKA-0831000", "PBANKA-1102200")
mutant_genes_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0413400", "PBANKA-0716500", "PBANKA-0102400",  "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

## these get defined later on, but are replicated above here for plotting
asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## copy the clusters so you don't permanently edit the master
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- tenx.justwt.integrated@meta.data$seurat_clusters

## reorder the levels so you can plot the cluters as you wish
my_levels <- c(asexual_early_clusters,asexual_late_clusters, bipotential_clusters, male_clusters, female_clusters)

## reorder the levels
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- factor(x = tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting, levels = my_levels)

## rename clusters so that they are intuitive
# this trick is from here: http://www.cookbook-r.com/Manipulating_data/Renaming_levels_of_a_factor/
levels(tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting) <- list(Asexual_1="9", 
                                                                              Asexual_2="4", 
                                                                              Asexual_3="15", 
                                                                              Asexual_4 = "8", 
                                                                              Asexual_5 = "1",
                                                                              Asexual_6=  "14", 
                                                                              Asexual_7 = "2", 
                                                                              Asexual_8 = "10",
                                                                              Asexual_9 = "3",
                                                                              Asexual_10 = "0",
                                                                              Asexual_11 = "6",
                                                                              Asexual_12 = "5",
                                                                              Asexual_13 = "7",
                                                                              Asexual_14 = "12",
                                                                              Asexual_15 = "18",
                                                                              Asexual_16 = "20",
                                                                              Asexual_17 = "23",
                                                                              Bipotential = "11",
                                                                              Male_1 = "16",
                                                                              Male_2 = "13",
                                                                              Female_1 = "21",
                                                                              Female_2 = "22",
                                                                              Female_3 = "19",
                                                                              Female_3 = "17"
                                                                              )

### Annotation set-up

## extract pseudotime numbers and identity of cells to a dataframe
df_pt_id <- tenx.justwt.integrated@meta.data[,c("old_pt_values", "monocle_sex", "seurat_clusters_dot_plotting", "Prediction.Spearman.", "Prediction.Spearman._Kasia")]

## make a new column
df_pt_id$colour <- NA

## assign bins to each of the values
## help here: https://stackoverflow.com/questions/9946630/colour-points-in-a-plot-differently-depending-on-a-vector-of-values 
df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Male", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Male", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Female", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Female", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$old_pt_values,breaks = 100))

## make colour ramps
asex_ramp <- colorRampPalette(c("#D5E3F5", "#0052c5"))
male_ramp <- colorRampPalette(c("white", "yellow", "#016c00"))
female_ramp <- colorRampPalette(c("yellow", "#a52b1e"))
bipot_ramp <- colorRampPalette(c("white", "#ffe400"))

## assign values to each cluster
## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "colour"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
## BECAUSE we have ordered the clusters already, we can simply take the row index for this bit
df_annotation$colour <- NA
df_annotation[1:17, ]$colour <- asex_ramp(100)[df_annotation[1:17, ]$x]
df_annotation[18, ]$colour <- bipot_ramp(100)[df_annotation[18, ]$x]
df_annotation[19:20, ]$colour <- male_ramp(100)[df_annotation[19:20, ]$x]
df_annotation[21:23, ]$colour <- female_ramp(100)[df_annotation[21:23, ]$x]

## plot annotation 
## this really helped: https://www.biostars.org/p/396810/
h2 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     #legend <- plot_grid(get_legend(h2), get_legend(h1), ncol = 1)
 h2 <- h2 + theme(legend.position = "none")
 #   geom_point(col = df_umap_plot$colour)
 
 h1 <- ggplot(df_annotation)+
  geom_point(mapping = aes(x = Group.1, y = 1),
            col = df_annotation$colour,
            size = 5)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     #legend <- plot_grid(get_legend(h2), get_legend(h1), ncol = 1)
 h1 <- h1 + theme(legend.position = "none")
 #   geom_point(col = df_umap_plot$colour)

 ## add predicted time point
 ## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "Prediction.Spearman."], list(df_pt_id$seurat_clusters_dot_plotting), mean)
df_annotation$colour <- NA
df_annotation$colour <- viridis(300)[(df_annotation$x)*10]

h3 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     legend_h3 <- get_legend(h3)
 h3 <- h3 + theme(legend.position = "none")

  h3 <- ggplot(data = df_annotation, 
              mapping = aes(x = Group.1, fill=x)
              ) +
       geom_bar(col = "#FFFFFF", width = 1)+
       theme_void() +
       theme(panel.spacing.x = unit(1, "mm")) +
       scale_fill_viridis(option = 'cividis')
 legend_h3 <- get_legend(h3)
 h3 <- h3 + theme(legend.position = "none")
 
 ## add kasia data
  ## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "Prediction.Spearman._Kasia"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
df_annotation$colour <- NA
df_annotation$colour <- viridis(300)[(df_annotation$x)*10]

h4 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))+
     facet_grid(.~colour, scales = "free_x")
     legend <- plot_grid(get_legend(h4), ncol = 1)
    legend_h4 <- get_legend(h4)
 h4 <- h4 + theme(legend.position = "none")

 h4 <- ggplot(data = df_annotation, 
              mapping = aes(x = Group.1, fill=x)
              ) +
       geom_bar(col = "#FFFFFF", width = 1)+
       theme_void() +
       theme(panel.spacing.x = unit(1, "mm")) +
       scale_fill_viridis()
 legend_h4 <- get_legend(h4)
 h4 <- h4 + theme(legend.position = "none")

### Plot
dot_plot_markers <- DotPlot(tenx.justwt.integrated, 
                            features = c(marker_genes_list, rev(mutant_genes_list)), 
                            group.by = "seurat_clusters_dot_plotting", 
                            dot.min = 0.00001,
                            assay = 'RNA') +
  theme_classic() +
  coord_fixed() +
  coord_flip() +
  # change appearance and remove axis elements, and make room for arrows
  theme(axis.text.x = element_text(size=16, angle = 45, hjust=1,vjust=1, family = "Arial"), 
        axis.text.y = element_text(size=16, face="italic"), 
        text=element_text(size=16, family="Arial", colour="black"), 
        legend.position = "bottom", 
        legend.direction = "horizontal", 
        legend.box = "vertical", 
        plot.title = element_blank(), 
        plot.margin = unit(c(1,3,1,3), "lines"), 
        axis.line = element_blank(),
        panel.border = element_rect(colour = "black", fill=NA, size=0.5)) +
  #change the colours
  #scale_colour_viridis(option = "inferno", guide = "colourbar", na.value="white", begin = 0, end = 1, direction = 1) +
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## change x axis label
  # labs(x = "Marker Genes", y = "Cluster", title = "Expression of Marker Genes by Cluster") 
  labs(x = "", y = "", title = "") +
  ## add arrows
  #annotate("segment", x = 5.5, xend = 5.5, y = 21.5, yend = 25, colour = "green", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  #annotate("segment", x = 5.5, xend = 5.5, y = 16.5, yend = 21.5, colour = "red", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  #annotate("segment", x = 5.5, xend = 5.5, y = 0, yend = 15.5, colour = "grey", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  ## annotate asex
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## annotate bipotential
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters, bipotential_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## annotate sexes
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters, bipotential_clusters, male_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## change label on bottom of plot so we can indicate markers
  scale_x_discrete(labels = rev(c("gd1", "md1", "md2", "md3", "md4", "md5", "fd1", "fd2", "fd3", "fd4", "msp8", "msp1", "mg1", "ccp2", "ap2g"))) +
  ## change label on bottom of plot so we can indicate markers
  scale_y_discrete(labels = c("Asexual 1", "Asexual 2" , "Asexual 3", "Asexual 4", "Asexual 5", "Asexual 6", "Asexual 7", "Asexual 8",  "Asexual 9", "Asexual 10", "Asexual 11", "Asexual 12", "Asexual 13", "Asexual 14", "Asexual 15", "Asexual 16", "Asexual 17", "Bipotential", "Male 1", "Male 2", "Female 1", "Female 2", "Female 3")) +
  ## change name of legends
  guides(col=guide_colorbar(title = 'Scaled Average Expression'),
         size=guide_legend("% of cells expressing"))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
## view
#print(dot_plot_markers)

plot <- plot_grid(h4, h3, h1, dot_plot_markers, align = "v", ncol = 1, axis = "tb", rel_heights = c(0.5, 0.5, 0.5, 18)) 
Removed 37 rows containing missing values (geom_point).font family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font database
dot_plot <- plot_grid(plot, legend_h3, legend_h4, nrow = 1, rel_widths = c(10, 1.5, 1.5))

dot_plot

save

ggsave("../images_to_export/dot_plot_all.png", plot = dot_plot, device = "png", path = NULL, scale = 1, width = 29.7, height = 21, units = "cm", dpi = 300, limitsize = TRUE)

9. Subset sexual cells

Make a subsetted Seurat object of sexual cells.

Include the pre-branch too as well as any weird clusters that may have clustered out.

it’s been a while since we looked at the clusters so let’s check them out again:

## Plot
DimPlot(tenx.justwt.integrated, label = TRUE, repel = FALSE, pt.size = 0.05, group.by = "seurat_clusters", dims = c(1,2), reduction = "umap") + coord_fixed()

## plot
list_UMAPs_by_cluster[[1]] + list_UMAPs_by_cluster[[2]] + list_UMAPs_by_cluster[[3]] + list_UMAPs_by_cluster[[4]] + list_UMAPs_by_cluster[[5]] + list_UMAPs_by_cluster[[6]] + list_UMAPs_by_cluster[[7]] + list_UMAPs_by_cluster[[8]] + list_UMAPs_by_cluster[[9]] + list_UMAPs_by_cluster[[10]] + list_UMAPs_by_cluster[[11]] + list_UMAPs_by_cluster[[12]] + list_UMAPs_by_cluster[[13]] + list_UMAPs_by_cluster[[14]] + list_UMAPs_by_cluster[[15]] + list_UMAPs_by_cluster[[16]] + list_UMAPs_by_cluster[[17]] + list_UMAPs_by_cluster[[18]] + list_UMAPs_by_cluster[[19]] + list_UMAPs_by_cluster[[20]] + list_UMAPs_by_cluster[[21]] + list_UMAPs_by_cluster[[22]] + list_UMAPs_by_cluster[[23]] + list_UMAPs_by_cluster[[24]]

Define cells and subset

asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## define cells
cell_names_subset_monocle_ids <- rownames(tenx.justwt.integrated@meta.data[tenx.justwt.integrated@meta.data$monocle_sex %in% c("Asexual_Early", "Bipotential", "Male", "Female"), ])

## 3, 0, 6, 5 are early clusters of asexuals before the branch
cell_names_subset_cluster_ids <- rownames(tenx.justwt.integrated@meta.data[tenx.justwt.integrated@meta.data$seurat_clusters %in% c(male_clusters, female_clusters, bipotential_clusters, 3, 0, 6, 5), ])

cell_names_subset_intersect <- intersect(cell_names_subset_monocle_ids, cell_names_subset_cluster_ids)

## subset cells into new object
tenx.justwt.integrated.sex <- subset(tenx.justwt.integrated, cells = cell_names_subset_intersect)

inspect/check

## inspect object
tenx.justwt.integrated.sex

## look at original UMAP
DimPlot(tenx.justwt.integrated.sex, label = TRUE, repel = TRUE, pt.size = 0.1, split.by = "experiment", dims = c(1,2), reduction = "umap") + coord_fixed()

Remove contaminant asexual cells

we want to remove:

## look at original UMAP
plot_sexual_subsetting <- DimPlot(tenx.justwt.integrated.sex, label = TRUE, repel = TRUE, pt.size = 0.1, dims = c(1,2), reduction = "umap") + 
  coord_fixed() + 
  geom_vline(aes(xintercept = -1, alpha = 5))

plot_sexual_subsetting
## extract cell embeddings
df_sex_cell_embeddings <- as.data.frame(tenx.justwt.integrated.sex@reductions[["umap"]]@cell.embeddings)

## subset anything lower than -0.8 in UMAP 2 and -0.1 in UMAP 1
remove_cells <- row.names(df_sex_cell_embeddings[which(df_sex_cell_embeddings$UMAP_1 < -1), ])

## plot these cells
DimPlot(tenx.justwt.integrated.sex, label = FALSE, repel = TRUE, pt.size = 0.1, cells.highlight = remove_cells, dims = c(1,2), reduction = "umap") + 
  coord_fixed() + 
  scale_color_manual(values=c("#000000", "#f54e1e")) + 
  theme_void() + 
  labs(title = paste("cells highlighted will be removed")) + 
  theme(plot.title = element_text(hjust = 0.5), legend.position = "none")

Final Subset

tenx.justwt.integrated.sex
An object of class Seurat 
10116 features across 2817 samples within 2 assays 
Active assay: RNA (5098 features, 0 variable features)
 1 other assay present: integrated
 2 dimensional reductions calculated: pca, umap

copy old clusters over

## copy old clusters
tenx.justwt.integrated.sex <- AddMetaData(tenx.justwt.integrated.sex, tenx.justwt.integrated.sex@meta.data$seurat_clusters, col.name = "post_integration_clusters")

10. Sex assignment of mutants

A. Seurat Method

## find transfer anchors
DefaultAssay(tenx.justwt.integrated) <- "integrated"
merge.anchors <- FindTransferAnchors(reference = tenx.justwt.integrated, query = GCSKO_mutants, 
    dims = 1:30)
Performing PCA on the provided reference using 2000 features as input.
Projecting PCA
Finding neighborhoods
Finding anchors
    Found 920 anchors
Filtering anchors
    Retained 610 anchors
## transfer data between ref and query
predictions <- TransferData(anchorset = merge.anchors, refdata = tenx.justwt.integrated$monocle_sex, 
    dims = 1:30)
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Predicting cell labels
## add meta data to object
GCSKO_mutants <- AddMetaData(GCSKO_mutants, metadata = predictions)

## new object from this
mutant_seurat <- GCSKO_mutants

## look at breakdown of mutant by designation
df <- as.data.frame(mutant_seurat@meta.data)
table(df$predicted.id, df$identity_name_updated)
               
                fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_Early   7  71   7  11  19   7  13  14   4  66        77
  Asexual_Late   60  52  94  14 148 121  43 187  41  43       194
  Female         21  62  19  23   6 127 205  88  15  25       197
  Male           65  55  14  45  60   0   0  47  17 112       221
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- df[df$genetic_background =="PBANKA_820", ]
table(df_820$predicted.id, df_820$fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   0      69       1
  Asexual_Late   33     459      16
  Female          2     342     240
  Male          182      49       0

Calculate sex ratios

## use designations above for sexes
male_cells <- rownames(mutant_seurat@meta.data[mutant_seurat@meta.data$predicted.id == "Male", ])
female_cells <- rownames(mutant_seurat@meta.data[mutant_seurat@meta.data$predicted.id == "Female", ])
ss2_mutants_final_male <- subset(mutant_seurat, cells = male_cells)
ss2_mutants_final_female <- subset(mutant_seurat, cells = female_cells)

## inspect
ss2_mutants_final_male
An object of class Seurat 
5018 features across 636 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
ss2_mutants_final_female
An object of class Seurat 
5018 features across 788 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
## calculate sex ratios
##subset out H, sorted cells:
df_male <- ss2_mutants_final_male@meta.data[ss2_mutants_final_male@meta.data$exclude_for_sex_ratio == FALSE,]

dim(df_male)
[1] 454 124
df_female <- ss2_mutants_final_female@meta.data[ss2_mutants_final_female@meta.data$exclude_for_sex_ratio == FALSE,]

dim(df_female)
[1] 546 124
## make dataframe
df_sex_ratio <- merge(
  as.data.frame(table(df_male$sub_name_updated)), 
  as.data.frame(table(df_female$sub_name_updated)), 
  by = "Var1", all=TRUE)

# or use identity_updated

## add names
names(df_sex_ratio) <- c("genotype", "male", "female")

## change the NAs to 0
df_sex_ratio[is.na(df_sex_ratio)] <- 0

## collapse 820 wild-types together
combined_m <- df_sex_ratio[df_sex_ratio$genotype == "WT-820_3_5", ]$male + df_sex_ratio[df_sex_ratio$genotype == "WT-820", ]$male
combined_f <- df_sex_ratio[df_sex_ratio$genotype == "WT-820_3_5", ]$female + df_sex_ratio[df_sex_ratio$genotype == "WT-820", ]$female
df_sex_ratio <- rbind(df_sex_ratio, c("WT-820-combined", combined_m, combined_f))
invalid factor level, NA generated
# remove old rows
df_sex_ratio <- df_sex_ratio[-which(df_sex_ratio$genotype == "WT-820_3_5" | df_sex_ratio$genotype == "WT-820"), ]
# need to make numeric again
df_sex_ratio$male <- as.numeric(df_sex_ratio$male)
df_sex_ratio$female <- as.numeric(df_sex_ratio$female)
df_sex_ratio$genotype <- as.character(df_sex_ratio$genotype)
# add name for WT combined
df_sex_ratio$genotype[17] <- "WT-820-combined"

## calculate sex ratio
df_sex_ratio$sex_ratio <- (df_sex_ratio$male + 0.1)/(df_sex_ratio$female + 0.1)

## log sex ratio
df_sex_ratio$sex_ratio_log <- log10(df_sex_ratio$sex_ratio)

##view
df_sex_ratio
## remove WT-2 because it is really inappropriate to have a sex ratio for this:
df_sex_ratio <- df_sex_ratio[-which(df_sex_ratio$genotype == "WT-md5"),]

plot

B. SCMAP Method

Build the index

### Making an ortholog reference index

## load in mca data
#counts <- read.csv("../scmap/allpb10x_counts.csv", row.names = 1)
#pheno <- read.csv("../scmap/allpb10x_pheno.csv")
#ggplot(pheno, aes(x=PC2_3d, y = PC3_3d,colour=absclust3)) + geom_point()

## load required libraries
library(scmap) #https://bioconductor.org/packages/release/bioc/html/scmap.html 
library(SingleCellExperiment) #

#prep the SCE, if was originally a Suerat object need the dfs to be regular matrices
#pb_filtered_sce_orth <- pb_filtered_sce_orth[, colData(pb_filtered_sce_orth)$absclust3 != "8"]
#sce <- pb_filtered_sce_orth
#pca <- plotPCA(sce)
#pcs <- pca$data
#table(rownames(pcs)==colnames(sce))
#colData(sce) <- cbind(colData(sce), pcs)
#rowData(sce)$feature_symbol <- rowData(sce)$gene

## extract data from Seurat
#cells_tenx <- rownames(tenx.justwt.integrated@meta.data[which(tenx.justwt.integrated@meta.data$experiment == "tenx_5k"), ])
#tenx.justwt.integrated.10k <- subset(tenx.justwt.integrated, cells = cells_tenx)
counts = as.matrix(GetAssayData(tenx.justwt.integrated, slot = "counts", assay = "RNA"))
pheno = as.data.frame(tenx.justwt.integrated@meta.data)

## add UMAP coordinates
df_sex_cell_embeddings <- as.data.frame(tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings)
pheno <- cbind(pheno, df_sex_cell_embeddings)

## Set up object
sce <- SingleCellExperiment(list(counts=counts),
    colData=DataFrame(label=pheno),
    rowData=DataFrame(feature_symbol=rownames(counts)))
sce
class: SingleCellExperiment 
dim: 5098 6880 
metadata(0):
assays(1): counts
rownames(5098): PBANKA-0000101 PBANKA-0000301 ... PBANKA-MIT0360 PBANKA-MIT0370
rowData names(1): feature_symbol
colnames(6880): AAACCTGGTAAGGGCT AAACCTGGTGCACTTA ... SC25027_8_95 SC25027_8_96
colData names(127): label.orig.ident label.nCount_RNA ... label.UMAP_1 label.UMAP_2
reducedDimNames(0):
altExpNames(0):
## manual logging
#counts_1 <- assay(sce, "counts")
#libsizes <- colSums(counts_1)
#size.factors <- libsizes/mean(libsizes)
#logcounts(sce) <- log2(t(t(counts_1)/size.factors) + 1)
#counts(sce) <- as.matrix(counts(sce))
#logcounts(sce) <- as.matrix(logcounts(sce))
logcounts(sce) <- as.matrix(GetAssayData(tenx.justwt.integrated, slot = "data", assay = "RNA"))

## remove features with duplicated names
sce <- sce[!duplicated(rownames(sce)), ]

## build scmap-cell reference index, save this rds
sce <- selectFeatures(sce, suppress_plot = FALSE, n_features = 2000)

table(rowData(sce)$scmap_features)

FALSE  TRUE 
 3098  2000 
set.seed(1)
sce <- indexCell(sce, M = 50, k = 80)
names(metadata(sce)$scmap_cell_index)
[1] "subcentroids" "subclusters" 
length(metadata(sce)$scmap_cell_index$subcentroids)
[1] 50
dim(metadata(sce)$scmap_cell_index$subcentroids[[1]])
[1] 40 80
metadata(sce)$scmap_cell_index$subcentroids[[1]][,1:5]
                        1           2           3           4          5
PBANKA-0100200 0.14630862 0.526027391 0.043704597 0.084187544 0.27749519
PBANKA-0100700 0.09460507 0.073257106 0.313286733 0.370676472 0.27852452
PBANKA-0100900 0.09923532 0.087566303 0.059203198 0.094759828 0.06865377
PBANKA-0101000 0.04763362 0.033790484 0.035038280 0.029494053 0.09082912
PBANKA-0101200 0.05167727 0.100910226 0.041157644 0.087829422 0.04947390
PBANKA-0101300 0.03427392 0.000000000 0.006482623 0.017440407 0.04685456
PBANKA-0101400 0.12483604 0.023321169 0.056473567 0.214402432 0.30191506
PBANKA-0101500 0.03194160 0.050889592 0.037542520 0.040676819 0.02895481
PBANKA-0101600 0.03798147 0.007504403 0.028087301 0.055265292 0.02882148
PBANKA-0101800 0.28129376 0.098383830 0.133405404 0.110619710 0.08911439
PBANKA-0101900 0.04066573 0.007504403 0.033564638 0.036681755 0.18011835
PBANKA-0102000 0.07611798 0.066861770 0.012354195 0.077811108 0.09136082
PBANKA-0102200 0.06226485 0.251753986 0.605044037 0.076494250 0.11263897
PBANKA-0102800 0.06418848 0.030164171 0.042579458 0.058224917 0.09315054
PBANKA-0103100 0.11743208 0.010838894 0.026223349 0.027978543 0.07163404
PBANKA-0103800 0.04052086 0.092749297 0.037663604 0.051866920 0.05463320
PBANKA-0104100 0.10698392 0.000000000 0.000000000 0.021640058 0.01323152
PBANKA-0104900 0.15330358 0.040643918 0.047150266 0.096686040 0.08016202
PBANKA-0105100 0.00774803 0.000000000 0.000000000 0.000000000 0.01212389
PBANKA-0105200 0.14295074 0.090669292 0.195180247 0.390381118 0.10203677
PBANKA-0105300 0.07266638 0.035247576 0.083080416 0.026830263 0.08893071
PBANKA-0105500 0.05972304 0.130442176 0.613873789 0.124039039 0.06698287
PBANKA-0105600 0.10822754 0.303080159 0.124325455 0.169514333 0.18211011
PBANKA-0106100 0.08682023 0.000000000 0.037839217 0.049002485 0.05906248
PBANKA-0106300 0.01815899 0.000000000 0.007580943 0.002964005 0.01617340
PBANKA-0106500 0.06709366 0.160165980 0.103227974 0.026045686 0.29711821
PBANKA-0106600 0.06615049 0.041341810 0.011974030 0.090413046 0.08166804
PBANKA-0106900 0.06772833 0.099129853 0.058992669 0.401040855 0.09974455
PBANKA-0106950 0.07031790 0.010838894 0.008323748 0.062299847 0.04044479
PBANKA-0107100 0.17579265 0.059474584 0.032474136 0.119798580 0.10795614
PBANKA-0107300 0.52569711 0.140088244 0.000000000 0.452049173 0.43157921
PBANKA-0107400 0.40027934 0.554030211 0.028538986 0.179514374 0.30285506
PBANKA-0107500 0.06729382 0.074821209 0.023884962 0.041973749 0.10242388
PBANKA-0107600 0.10346987 0.295645683 0.107376132 0.291553393 0.09681055
PBANKA-0108200 0.10862989 0.032331520 0.101822888 0.088844686 0.07713661
PBANKA-0108500 0.02145669 0.030583685 0.024050668 0.031126013 0.02086511
PBANKA-0108600 0.24498462 0.045568380 0.056630631 0.095147870 0.18860540
PBANKA-0108700 0.39883605 0.152992706 0.123346730 0.108083282 0.35455198
PBANKA-0108800 0.08791660 0.022213910 0.000000000 0.016375691 0.04375594
PBANKA-0108900 0.03944358 0.012735216 0.017821829 0.063455344 0.06855602
dim(metadata(sce)$scmap_cell_index$subclusters)
[1]   50 6880
#saveRDS(pb_filtered_sce_orth, file="pb_filtered_sce_orthindex_20181109.rds")

Map to the index

scmapCell_results$wt$cells[, 1:3]
      SC26779_5_100 SC26779_5_101 SC26779_5_102
 [1,]          6554          6685          6163
 [2,]          6247          6528          6200
 [3,]          6734          6436          6466
 [4,]          6323          6588          6124
 [5,]          6468          6470          6871
 [6,]          6685          6323          6563
 [7,]          6470          6606          6456
 [8,]          6436          6614          6149
 [9,]          6515          6608          6494
[10,]          6614          6854          6647
## get cell indexes 
getcells <- scmapCell_results$wt$cells[1, ]
## exctract cells metadata from index
cdsce <- colData(sce)[getcells, ]
## extract similarities
topsim <- scmapCell_results$wt$similarities[1, ]
## get name of top cell matched
mutants.sce$topcell <- rownames(cdsce)
## get sex id
mutants.sce$topcell_ac <- cdsce$label.monocle_sex
## get coordinates of matched cell
mutants.sce$indexPC1 <- cdsce$label.UMAP_1
mutants.sce$indexPC2 <- cdsce$label.UMAP_2
#mutants.sce$pbpt <- cdsce$pseudotime
#mutants.sce$pbbulk <- cdsce$bulk
mutants.sce$topcell_sp <- mutants.sce$topcell_ac
mutants.sce$topsim <- topsim
mutants.sce$topcell_sp[mutants.sce$topsim < 0.4] <- "unassigned"
table(mutants.sce$topcell_sp)

Asexual_Early  Asexual_Late        Female          Male    unassigned 
          335           346           186           548          1302 
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$topcell_sp, df_820$label.fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   0      89       2
  Asexual_Late    5     150       3
  Female          2      84      54
  Male          158      47       0
  unassigned     52     549     198
table(colData(mutants.sce)$topcell_sp, colData(mutants.sce)$label.identity_name_updated)
               
                fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_Early   9  74  13   9  20  12  17  20   8  67        86
  Asexual_Late   14  21  37   8  36  45  21  43  20  22        79
  Female          1   2   7   2   0  17  39  44   3   6        65
  Male           64  51  14  41  25   0   0  34  12 104       203
  unassigned     65  92  63  33 152 181 184 195  34  47       256
#### TOP 3NN method

#This function makes a list of the PC means for each cell and then do.call below rbinds them into a dataframe called big_data

datalist = list()

for (i in colnames(scmapCell_results$wt$cells)) {
  
  getcellstest <- scmapCell_results$wt$cells[1:3, i]
  cdscetest <- colData(sce)[getcellstest, ]
  PC1mean <- mean(cdscetest$label.UMAP_1)
  PC2mean <- mean(cdscetest$label.UMAP_2)
  # ... make some data
  dat <- data.frame(i, PC1mean, PC2mean)
  dat$i <- i  # maybe you want to keep track of which iteration produced it?
  datalist[[i]] <- dat # add it to your list
}

big_data = do.call(rbind, datalist)
# or big_data <- dplyr::bind_rows(datalist)
# or big_data <- data.table::rbindlist(datalist)

test <- big_data[1, ]

df <- data.frame(X=colData(sce)$label.UMAP_1, Y=colData(sce)$label.UMAP_2, row.names = rownames(colData(sce)))

#the snap function snaps to the nearest cell in PC coordiantes
snap <- function(df, test){
  require(Biobase)
  d <- matchpt(as.matrix(df),
               as.matrix(data.frame(X=test$PC1mean,Y=test$PC2mean)))
  
  min_row <- rownames(d[d$distance==min(d$distance),])
  
  test$X_snap <- unique(df[min_row,"X"])
  test$Y_snap <- unique(df[min_row,"Y"])
  test$pb_cell <- min_row
  
  test
}

#this loops through each cell and in big_data and runs the snap function
datalist2 = list()
colnames(big_data) <- c("sample_id", "PC1mean", "PC2mean")
for (i in rownames(big_data)) {
  test <- big_data[i, ]
  coord <- snap(df, test)
  coord$i <- i
  datalist2[[i]] <- coord
}
big_data2 = do.call(rbind, datalist2)


table(rownames(big_data2)==rownames(colData(mutants.sce)))

TRUE 
2717 
allpbcd <- colData(sce)
allpbcd <- as.data.frame(allpbcd)
pbabsclust <- allpbcd[, c("label.pt_id_cols", "label.identity_name_updated", "label.monocle_sex"), drop=FALSE]
pbabsclust$pb_sample_id <- rownames(pbabsclust)

# Now merge the pc cell asignments with their abs clust and get in the right order
big_data3 <- merge(big_data2, pbabsclust, by.x = "pb_cell", by.y = "pb_sample_id", all.x=TRUE, all.y=FALSE)
big_data4 <- big_data3[match(rownames(big_data2), big_data3$sample_id), ]


colors <- c("6"="#78C679",
            "2"="#D1EC9F",
            "0"="#FEB24C",
            "1"="#F4CF63",
            "3"="#FEEEAA",
            "4"="#85B1D3",
            "7"="#9ecae1",
            "5"="#C9E8F1",
            "M"= "#B7B7D8",
            "F"="#9C96C6",
            "unassigned"="black")

ggplot(big_data4, aes(PC1mean, PC2mean)) +
  geom_point(col = big_data4$label.pt_id_cols) +
                     theme_void() +
                     coord_fixed()


#+ geom_point(aes(colour=factor(big_data4$label.label.pt_id_cols))) + scale_color_manual(values = colors) 

                     

ggplot(big_data4, aes(X_snap, Y_snap)) +
  geom_point(col = big_data4$label.pt_id_cols) +
                     theme_void() +
                     coord_fixed() 


#+ geom_point(aes(colour=factor(big_data4$label.label.pt_id_cols))) + scale_color_manual(values = colors) 

##add info to SCE and save colData, to be an assigned cell all 3NN must have a cos sim >0.4
scmapCell_results$wt$similarities[, 1:3]
      SC26779_5_100 SC26779_5_101 SC26779_5_102
 [1,]     0.2654243     0.3283723     0.4455592
 [2,]     0.2657229     0.3322655     0.4476295
 [3,]     0.2649363     0.3346425     0.4463425
 [4,]     0.2685002     0.3314723     0.4455779
 [5,]     0.2655940     0.3347640     0.4463982
 [6,]     0.2654118     0.3351348     0.4472700
 [7,]     0.2659329     0.3289516     0.4482864
 [8,]     0.2683255     0.3303473     0.4451670
 [9,]     0.2668498     0.3284948     0.4503529
[10,]     0.2664087     0.3284307     0.4486978
topsim1 <- scmapCell_results$wt$similarities[1, ]
topsim2 <- scmapCell_results$wt$similarities[2, ]
topsim3 <- scmapCell_results$wt$similarities[3, ]

table(big_data4$sample_id==rownames(colData(mutants.sce)))

TRUE 
2717 
#pfobj$pb_cell <- big_data4$pb_cell
#pfobj$PC1mean <- big_data4$PC1mean
bd4 <- big_data4[, c("pb_cell", "sample_id", "PC1mean", "PC2mean", "X_snap", "Y_snap", "label.pt_id_cols", "label.identity_name_updated", "label.monocle_sex")]

colData(mutants.sce) <- cbind(colData(mutants.sce), bd4)

mutants.sce$topsim1 <- topsim1
mutants.sce$topsim2 <- topsim2
mutants.sce$topsim3 <- topsim3
mutants.sce$stage_pred <- big_data4$label.monocle_sex
mutants.sce$stage_pred[mutants.sce$topsim1 < 0.4 | mutants.sce$topsim2 < 0.4 | mutants.sce$topsim3 < 0.4] <- "unassigned"
table(mutants.sce$stage_pred)

Asexual_Early  Asexual_Late   Bipotential        Female          Male    unassigned 
          325           345             1           182           546          1318 
#write.csv(bd4, "pfcellassignmentswithmean3nn_20181029.csv")
#write.csv(colData(pfobj), "pf3d7100scmapclusts2methodindexn100_20190107.csv")
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$stage_pred, df_820$label.fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   1      81       2
  Asexual_Late    3     153       3
  Bipotential     0       1       0
  Female          2      83      52
  Male          156      47       0
  unassigned     55     554     200
table(colData(mutants.sce)$stage_pred, colData(mutants.sce)$label.identity_name_updated)
               
                fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_Early   7  73  11   9  20  10  15  20   7  68        85
  Asexual_Late   16  22  39   8  34  46  23  41  20  21        75
  Bipotential     0   0   0   0   0   0   0   0   0   0         1
  Female          1   2   7   2   0  16  39  44   3   6        62
  Male           64  51  14  41  25   0   0  33  12 104       202
  unassigned     65  92  63  33 154 183 184 198  35  47       264

make final plot with MCA data below

## Read in MCA data
pheno <- read.csv("../scmap/allpb10x_pheno.csv")
## extract rows needed for plotting
df_plot <- pheno[,c("PC2_3d", "PC3_3d", "absclust3")]
df_plot$experiment <- df_plot$absclust3

## extract rows needed for plotting from mapped object
df_plot_pm <- as.data.frame(colData(pm_ss2_field.sce.orth))
df_plot_pm <- df_plot_pm[ ,c("X_snap", "Y_snap", "label.absclust3")]
df_plot_pm$experiment <- "pm"
colnames(df_plot_pm) <- c("PC2_3d", "PC3_3d", "absclust3", "experiment")

## extract rows needed for plotting from mapped object
df_plot_pf <- as.data.frame(colData(pf_ss2_field.sce.orth))
df_plot_pf <- df_plot_pf[ ,c("X_snap", "Y_snap", "label.absclust3")]
df_plot_pf$experiment <- "pf"
colnames(df_plot_pf) <- c("PC2_3d", "PC3_3d", "absclust3", "experiment")

## bind together
df_plot <- rbind(df_plot, df_plot_pf, df_plot_pm)

colors <- c("6"="#78C679",
            "2"="#D1EC9F",
            "0"="#FEB24C",
            "1"="#F4CF63",
            "3"="#FEEEAA",
            "4"="#85B1D3",
            "7"="#9ecae1",
            "5"="#C9E8F1",
            "M"= "#B7B7D8",
            "F"="#9C96C6",
            "unassigned"="black",
            "pm" = "#dc65a4",
            "pf" = "#24245f")

## add alpha for plotting
df_plot$alpha[!df_plot$experiment == "pm"] <- 0.5
df_plot$alpha[df_plot$experiment == "pm"] <- 1
df_plot$alpha[df_plot$experiment == "pf"] <- 1

##plot
scmap_pca <- ggplot(df_plot, aes(x=PC2_3d, y = PC3_3d,colour=experiment, alpha = alpha)) + 
  geom_point() +
  theme_void() +
  scale_color_manual(values = colors) +
  ## remove alpha scale
  scale_alpha_continuous(guide=FALSE)
  ## draw ring around field samples
  #geom_point(data=df_plot[df_plot$experiment == "pm", ], pch=21, fill=NA, size=2, colour="black", stroke=1) +
  ## make non-field samples more opaque
  #geom_point(data=df_plot[-df_plot$experiment == "pm", ], alpha = 0.2)

## view
scmap_pca_2 <- scmap_pca + 
  guides(colour=guide_legend(override.aes = list(size=4)))

scmap_pca_2

save

#ggsave("../images_to_export/field_samples_scmap.png", plot = scmap_pca_2, device = "png", path = NULL, scale = 1, width = 15, height = 10, units = "cm", dpi = 300, limitsize = TRUE)

Overlap and validation

11. Save and Export

save

Save environment

## This saves everything in the global environment for easy recall later
#save.image(file = "GCSKO_merge.RData")
#load(file = "GCSKO_merge.RData")

Save object(s)

## Save an object to a file
saveRDS(tenx.justwt.integrated.sex, file = "../data_to_export/tenx.justwt.integrated.sex.RDS")
## Restore the object
#readRDS(file = "../data_to_export/tenx.mutant.integrated.sex.RDS")

## save integrated object to file
saveRDS(tenx.justwt.integrated, file = "../data_to_export/tenx.justwt.integrated.RDS") 
## restore the object
#tenx.justwt.integrated <- readRDS("../data_to_export/tenx.justwt.integrated.RDS")

## save monocle object
saveRDS(monocle.object.all, file = "../data_to_export/monocle.object.all.RDS") 
## restore the object
#monocle.object.all <- readRDS("../data_to_export/monocle.object.all.RDS")

## save integrated object to file
#saveRDS(GCSKO_mutants, file = "../data_to_export/GCSKO_mutants.RDS") 
## restore the object
#tenx.justwt.integrated <- readRDS("../data_to_export/tenx.justwt.integrated.RDS")

Clean up

#rm(ss2_wt_cells)
#rm(tenx.justwt.integrated)
#rm(tenx.justwt.list)

final figure construction

Cowplot(plot_grid), patchwork(wrap_plots), and ggpubr can all allow multiple plots to be plotted together.

## A
# umap_id_pt
## B
# marker gene expression
## C
# Mutant gene expression
## D
# Modules

#Figure_A <- grid.arrange(arrangeGrob(QC_composite_plot, QC_mito_violin, QC_mito_graph, QC_by_genotype, mapping_rate_plot), nrow=3), nrow=2, heights=c(10,2))

## cowplot method
## can use this for labels: toupper(letters)[1:10]

## C. Mutant genes
mutant_genes_figure <- plot_grid(
                                 ## marker genes starts
                                 marker_gene_plot_FAMB,
                                 marker_gene_plot_MSP8,
                                 marker_gene_plot_MSP1,
                                 marker_gene_plot_AP2G,
                                 marker_gene_plot_CCP2,
                                 marker_gene_plot_MG1,
                                 ## mutant genes starts  
                                 marker_gene_plot_gd1,
                                 marker_gene_plot_md1,
                                 marker_gene_plot_md2,
                                 marker_gene_plot_md3,
                                 marker_gene_plot_md4, 
                                 marker_gene_plot_md5,
                                 marker_gene_plot_fd1,
                                 marker_gene_plot_fd2,
                                 marker_gene_plot_fd3,
                                 marker_gene_plot_fd4, 
  label_size = 1, 
  nrow = 4)

## labels as uppercase letters:
#c(toupper(letters)[2:17])
# labels as roman numerals:
# c(tolower(as.roman(c(2:17))

Figure_publication <- plot_grid(umap_id_pt + theme(plot.margin = unit(c(0, 0, 0, 0), "cm")), 
                                mutant_genes_figure,
                                ## add empty plot to give spacing
                                ggplot() + theme_void(),
                                labels = c('A', 'B'), 
                                label_size = 12, 
                                ncol = 2, 
                                nrow=2, 
                                rel_heights = c(1, 1, 4), 
                                rel_widths = c(1, 2, 3))

Figure_publication

save

ggsave("../images_to_export/Figure_C.png", plot = Figure_publication, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)
layout <- "
AABB
DEFG
HIJK
LMNO
PQRS
"

Figure_publication <- (composition_umap_10x + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10))) +
(composition_umap_ss2 + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10))) +
#(UMAP_hoo + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10)) + labs(title="Predicted Asexual Cycle Real Timepoint")) +
#(UMAP_kasia + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10)) + labs(title="Predicted Gametocytogenesis Real Timepoint")) +
  ## marker genes
marker_gene_plot_FAMB +
marker_gene_plot_MSP8 +
marker_gene_plot_MSP1 +
marker_gene_plot_AP2G +
marker_gene_plot_CCP2 +
marker_gene_plot_MG1 +
  ## mutant genes starts  
marker_gene_plot_gd1 +
marker_gene_plot_md1 +
marker_gene_plot_md2 +
marker_gene_plot_md3 +
marker_gene_plot_md4 + 
marker_gene_plot_md5 +
marker_gene_plot_fd1 +
marker_gene_plot_fd2 +
marker_gene_plot_fd3 +
marker_gene_plot_fd4 + 
plot_layout(ncol = 4, 
            widths = c(1, 1, 1, 1),
            heights = c(2, 1, 1, 1, 1),
            design = layout
            )

Figure_publication

save

ggsave("../images_to_export/Figure_S2.png", plot = Figure_publication, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)

Appendix

Session Info

R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
 [1] stats4    parallel  grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] colourvalues_0.3.7          readxl_1.3.1                destiny_3.2.0               circlize_0.4.12            
 [5] gganimate_1.0.7             shiny_1.5.0                 monocle3_0.2.3.0            SingleCellExperiment_1.10.1
 [9] SummarizedExperiment_1.18.2 DelayedArray_0.14.1         matrixStats_0.57.0          GenomicRanges_1.40.0       
[13] GenomeInfoDb_1.24.2         IRanges_2.22.2              S4Vectors_0.26.1            Biobase_2.48.0             
[17] BiocGenerics_0.34.0         Nebulosa_1.2.0              reshape2_1.4.4              Hmisc_4.4-1                
[21] Formula_1.2-4               survival_3.2-7              lattice_0.20-41             gridExtra_2.3              
[25] dplyr_1.0.2                 patchwork_1.0.1             ggplot2bdc_0.3.2            cowplot_1.1.0              
[29] ggpubr_0.4.0                ggplot2_3.3.2               viridis_0.5.1               viridisLite_0.3.0          
[33] Seurat_3.2.2                colorspace_1.4-1           

loaded via a namespace (and not attached):
  [1] ggthemes_4.2.4            coda_0.19-4               tidyr_1.1.2               knitr_1.30               
  [5] irlba_2.3.3               data.table_1.13.2         rpart_4.1-15              RCurl_1.98-1.2           
  [9] generics_0.0.2            callr_3.5.1               leidenbase_0.1.2          usethis_1.6.3            
 [13] RANN_2.6.1                proxy_0.4-24              future_1.19.1             spatstat.data_1.4-3      
 [17] httpuv_1.5.4              assertthat_0.2.1          gifski_0.8.6              xfun_0.18                
 [21] hms_0.5.3                 evaluate_0.14             promises_1.1.1            DEoptimR_1.0-8           
 [25] fansi_0.4.1               progress_1.2.2            DBI_1.1.0                 igraph_1.2.6             
 [29] htmlwidgets_1.5.2         spdep_1.1-5               purrr_0.3.4               ellipsis_0.3.1           
 [33] RSpectra_0.16-0           crosstalk_1.1.0.1         ks_1.12.0                 backports_1.1.10         
 [37] deldir_0.1-29             vctrs_0.3.4               TTR_0.24.2                remotes_2.2.0            
 [41] ROCR_1.0-11               abind_1.4-5               RcppEigen_0.3.3.7.0       withr_2.3.0              
 [45] grr_0.9.5                 robustbase_0.93-7         checkmate_2.0.0           vcd_1.4-8                
 [49] sctransform_0.3.1         xts_0.12.1                prettyunits_1.1.1         mclust_5.4.7             
 [53] goftest_1.2-2             cluster_2.1.0             lazyeval_0.2.2            laeken_0.5.1             
 [57] crayon_1.3.4              units_0.6-7               slam_0.1-47               pkgconfig_2.0.3          
 [61] labeling_0.4.2            tweenr_1.0.1              nlme_3.1-149              pkgload_1.1.0            
 [65] nnet_7.3-14               devtools_2.3.2            rlang_0.4.8               globals_0.13.1           
 [69] lifecycle_0.2.0           miniUI_0.1.1.1            rsvd_1.0.3                cellranger_1.1.0         
 [73] rprojroot_1.3-2           polyclip_1.10-0           RcppHNSW_0.3.0            lmtest_0.9-38            
 [77] Matrix_1.2-18             raster_3.3-13             carData_3.0-4             Matrix.utils_0.9.8       
 [81] boot_1.3-25               zoo_1.8-8                 base64enc_0.1-3           ggridges_0.5.2           
 [85] GlobalOptions_0.1.2       processx_3.4.4            pheatmap_1.0.12           png_0.1-7                
 [89] bitops_1.0-6              KernSmooth_2.23-17        DelayedMatrixStats_1.10.1 classInt_0.4-3           
 [93] shape_1.4.5               stringr_1.4.0             jpeg_0.1-8.1              rstatix_0.6.0            
 [97] ggsignif_0.6.0            scales_1.1.1              memoise_1.1.0             magrittr_2.0.1           
[101] plyr_1.8.6                hexbin_1.28.1             ica_1.0-2                 gdata_2.18.0             
[105] zlibbioc_1.34.0           compiler_4.0.3            RColorBrewer_1.1-2        pcaMethods_1.80.0        
[109] fitdistrplus_1.1-1        cli_2.1.0                 LearnBayes_2.15.1         XVector_0.28.0           
[113] listenv_0.8.0             pbapply_1.4-3             ps_1.4.0                  htmlTable_2.1.0          
[117] ggplot.multistats_1.0.0   MASS_7.3-53               mgcv_1.8-33               tidyselect_1.1.0         
[121] stringi_1.5.3             forcats_0.5.0             yaml_2.2.1                latticeExtra_0.6-29      
[125] ggrepel_0.8.2             pbmcapply_1.5.0           tools_4.0.3               future.apply_1.6.0       
[129] rio_0.5.16                rstudioapi_0.11           foreign_0.8-80            smoother_1.1             
[133] scatterplot3d_0.3-41      farver_2.0.3              Rtsne_0.15                digest_0.6.27            
[137] BiocManager_1.30.10       Rcpp_1.0.6                car_3.0-10                broom_0.7.2              
[141] later_1.1.0.1             RcppAnnoy_0.0.16          httr_1.4.2                sf_0.9-6                 
[145] fs_1.5.0                  tensor_1.5                ranger_0.12.1             reticulate_1.18          
[149] splines_4.0.3             uwot_0.1.8                expm_0.999-5              spatstat.utils_1.17-0    
[153] sp_1.4-4                  spData_0.3.8              plotly_4.9.2.1            sessioninfo_1.1.1        
[157] xtable_1.8-4              jsonlite_1.7.1            spatstat_1.64-1           testthat_2.3.2           
[161] R6_2.5.0                  gmodels_2.18.1            pillar_1.4.6              htmltools_0.5.1.1        
[165] mime_0.9                  glue_1.4.2                fastmap_1.0.1             VIM_6.1.0                
[169] class_7.3-17              codetools_0.2-16          utf8_1.1.4                pkgbuild_1.1.0           
[173] mvtnorm_1.1-1             tibble_3.0.4              curl_4.3                  leiden_0.3.3             
[177] gtools_3.8.2              zip_2.1.1                 openxlsx_4.2.2            limma_3.44.3             
[181] rmarkdown_2.5             desc_1.2.0                munsell_0.5.0             e1071_1.7-4              
[185] GenomeInfoDbData_1.2.3    haven_2.3.1               gtable_0.3.0             

Expression plots

Expression - raw - Viridis

## find a good ring marker, to see if there is a better one than the ones reported
#markers_ring <- FindMarkers(tenx.justwt.integrated, ident.1 = c("4", "5", "16", "11", "7", "3", "9", "0", "22"))
#head(markers_ring)

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 


marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1319500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(ccp2), "(Female)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))
Error in italic(ccp2) : could not find function "italic"

Expression - raw - purple


marker_gene_ramp <- colorRampPalette(c("#D3D3D3", "#1D1564"))(50)

marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1319500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("CCP2 (Female)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0416100", coord.fixed = TRUE, 
                                    #min.cutoff = "q1", 
                                    dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MG1 (Male)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1437500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("AP2G (Commitment)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0831000", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MSP1 (Schizont)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1102200", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MSP8 (Asexual)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1101300", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("SBP1 (Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0722600", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("Fam-b2 (Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_HSP70 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0711900", coord.fixed = TRUE, 
                                      #min.cutoff = "q1", 
                                      dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("(HSP70; Reporter)","\n", "PBANKA_0711900")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)
font family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font database
marker_gene_plot_all

Expression - data - purple

# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD5
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_17 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1418100", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_2 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0102400", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_19 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0716500", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_20 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1435200", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_13 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0902300", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_10 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0413400", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md5")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_3 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0828000", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("gd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_oom <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1302700", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_29 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1447900", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_21 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1454800", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_17 , marker_gene_plot_2 , marker_gene_plot_19 , marker_gene_plot_20 , marker_gene_plot_13 , marker_gene_plot_10 , marker_gene_plot_3 , marker_gene_plot_oom , marker_gene_plot_29 , marker_gene_plot_21 , ncol = 4)
           
## print
mutant_expression_composite

Density Plots

Density - purple

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=marker_gene_ramp) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=marker_gene_ramp) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

Density -viridis

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)) )+ guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

Density - viridis

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0413400    GCSKO-10_820  MD5

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)) )+ guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0413400    GCSKO-10_820  MD5

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "wkde", slot = 'data')

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_color_continuous_sequential(palette = "Purples 2") + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_color_continuous_sequential(palette = "Purples 2") + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + 
                               coord_fixed() + 
                               theme_void() + 
                               labs(title = paste("md2")) + scale_color_continuous_sequential(palette = "Purples 2") + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
## old colour scale: scale_colour_gradientn(colours=marker_gene_ramp )

UMAP_composite_mutant_genes

LS0tCnN1YnRpdGxlOiAnR2FtZXRvY3l0ZSBEZXZlbG9wbWVudCBpbiA8aT5QbGFzbW9kaXVtIGJlcmdoZWk8L2k+Jwp0aXRsZTogfAogICFbXSguLi9HQ1NLT19sb2dvLmpwZyl7d2lkdGg9MzAwcHh9ICAKICBNZXJnaW5nIFNtYXJ0LXNlcTIgYW5kIDEwWCBEYXRhc2V0cyAtIHdpbGQtdHlwZSBvbmx5CmF1dGhvcjogIltBbmRyZXcgUnVzc2VsbF0oaHR0cHM6Ly9hamNydXNzZWxsLndpeHNpdGUuY29tL215c2l0ZS9hYm91dCkiCmluc3RpdHV0ZTogV2VsbGNvbWUgU2FuZ2VyIEluc3RpdHV0ZQpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlQiAlZCwgJVkiKWAnCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICAjdG9jX2Zsb2F0OiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KKioqCiMgMS4gSW50cm9kdWN0aW9uIGFuZCBBaW1zIHsudGFic2V0fQoKV2UgaGF2ZSBxdWFsaXR5LWNvbnRyb2xsZWQgdGhlIDEwWCBkYXRhIGFuZCB0aGUgU1MyIGRhdGEgYW5kIG5vdyBhcmUgbGVmdCB3aXRoIHRoZSBmb2xsb3dpbmcgb2JqZWN0czoKCjEwWCA1SyBkYXRhIC0gcGJfc2V4X2ZpbHRlcmVkCgoxMFggMzBLIGRhdGEgLSBwYl8zMGtfc2V4X2ZpbHRlcmVkIAoKU1MyIG11dGFudCBkYXRhIC0gc3MyX211dGFudHNfZmluYWwKCiMgMi4gUmVhZCBpbiB0aGUgZGF0YSAgey50YWJzZXR9CgojIyMgTG9hZC9JbnN0YWxsIHRoZSBSZXF1aXJlZCBQYWNrYWdlcwoKYGBge3IgbG9hZCBwYWNrYWdlcywgZWNobyA9IEZBTFNFfQojIyBDUkFOIHBhY2thZ2VzCgojIyBQYXRod29yayBpcyBuZWVkZWQgdG8gc3RpY2ggcGxvdHMgdG9nZXRoZXIgdXNpbmcgJysnCmlmKHJlcXVpcmUoInBhdGNod29yayIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgICBwcmludCgicGF0Y2h3b3JrIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoInRyeWluZyB0byBpbnN0YWxsIHBhdGNod29yayIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJwYXRjaHdvcmsiKQogICAgaWYocmVxdWlyZShwYXRjaHdvcmspKXsKICAgICAgICBwcmludCgicGF0Y2h3b3JrIGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgcGF0Y2h3b3JrIikKICAgIH0KfQoKIyMgdmlyaWRpcyBhbGxvd3MgZGlmZmVyZW50IGNvbG91cnMgdG8gYmUgYWRkZWQgdG8gcGxvdHMKaWYocmVxdWlyZSgidmlyaWRpcyIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgICBwcmludCgidmlyaWRpcyBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCB2aXJpZGlzIikKICAgIGluc3RhbGwucGFja2FnZXMoInZpcmlkaXMiKQogICAgaWYocmVxdWlyZSh2aXJpZGlzKSl7CiAgICAgICAgcHJpbnQoInZpcmlkaXMgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCB2aXJpZGlzIikKICAgIH0KfQoKIyMgU2V1cmF0IGlzIG5lZWRlZCBmb3IgbW9zdCBvZiB0aGlzIHNjcmlwdAppZihyZXF1aXJlKCJTZXVyYXQiLCBxdWlldGx5ID0gVFJVRSkpewogICAgcHJpbnQoIlNldXJhdCBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBTZXVyYXQiKQogICAgaW5zdGFsbC5wYWNrYWdlcygiU2V1cmF0IikKICAgIGlmKHJlcXVpcmUoU2V1cmF0KSl7CiAgICAgICAgcHJpbnQoIlNldXJhdCBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIFNldXJhdCIpCiAgICB9Cn0KCiMjIGNvd3Bsb3QgaXMgbmVlZGVkIGZvciBwbG90cyBpbiB0aGlzIHNjcmlwdAppZihyZXF1aXJlKCJjb3dwbG90IikpewogICAgcHJpbnQoImNvd3Bsb3QgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgY293cGxvdCIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJjb3dwbG90IikKICAgIGlmKHJlcXVpcmUoY293cGxvdCkpewogICAgICAgIHByaW50KCJjb3dwbG90IGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgY293cGxvdCIpCiAgICB9Cn0KCiMjIGdyaWRFeHRyYSBpcyBuZWVkZWQgZm9yIGdyaWQgZ3JhcGhpY3MgdG8gcGxvdCBtdWx0aXBsZSBwbG90cyBpbiB0aGUgc2FtZSB2aWV3CmlmKHJlcXVpcmUoImdyaWRFeHRyYSIpKXsKICAgIHByaW50KCJncmlkRXh0cmEgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgZ3JpZEV4dHJhIikKICAgIGluc3RhbGwucGFja2FnZXMoImdyaWRFeHRyYSIpCiAgICBpZihyZXF1aXJlKGdyaWRFeHRyYSkpewogICAgICAgIHByaW50KCJncmlkRXh0cmEgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCBncmlkRXh0cmEiKQogICAgfQp9CgojIyBncmlkIGlzIG5lZWRlZCBmb3IgZ3JpZC5hcnJhbmdlIGZ1bmN0aW9uIHRvIGNoYW5nZSBzaXplIG9mIHRpdGxlCmlmKHJlcXVpcmUoImdyaWQiKSl7CiAgICBwcmludCgiZ3JpZCBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBncmlkIikKICAgIGluc3RhbGwucGFja2FnZXMoImdyaWQiKQogICAgaWYocmVxdWlyZShncmlkKSl7CiAgICAgICAgcHJpbnQoImdyaWQgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCBncmlkIikKICAgIH0KfQoKIyNmb3IgZG9pbmcgYnVsayBjb3JyZWxhdGlvbiBjYWxjdWxhdGlvbnMKaWYocmVxdWlyZSgiSG1pc2MiKSl7CiAgICBwcmludCgiSG1pc2MgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgSG1pc2MiKQogICAgaW5zdGFsbC5wYWNrYWdlcygiSG1pc2MiKQogICAgaWYocmVxdWlyZShIbWlzYykpewogICAgICAgIHByaW50KCJIbWlzYyBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIEhtaXNjIikKICAgIH0KfQoKIyMgcmVzaGFwZTIgdG8gbWVsdCBkYXRhZnJhbWVzIGZvciBwbG90dGluZzoKaWYocmVxdWlyZSgicmVzaGFwZTIiKSl7CiAgICBwcmludCgicmVzaGFwZTIgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgcmVzaGFwZTIiKQogICAgaW5zdGFsbC5wYWNrYWdlcygicmVzaGFwZTIiKQogICAgaWYocmVxdWlyZShyZXNoYXBlMikpewogICAgICAgIHByaW50KCJyZXNoYXBlMiBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIHJlc2hhcGUyIikKICAgIH0KfQoKIyMgdG8gd29yayB3aXRoIGRhdGEgZnJhbWVzOgppZihyZXF1aXJlKCJkcGx5ciIpKXsKICAgIHByaW50KCJkcGx5ciBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBkcGx5ciIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCiAgICBpZihyZXF1aXJlKGRwbHlyKSl7CiAgICAgICAgcHJpbnQoImRwbHlyIGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgZHBseXIiKQogICAgfQp9CgojIyBub24tQ1JBTiBwYWNrYWdlcwoKIyMgdG8gbWFrZSBkZW5zaXR5IHBsb3RzIHNob3dpbmcgZ2VuZSBleHByZXNzaW9uCmlmKHJlcXVpcmUoIk5lYnVsb3NhIikpewogICAgcHJpbnQoIk5lYnVsb3NhIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoInRyeWluZyB0byBpbnN0YWxsIE5lYnVsb3NhIikKICAgIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigicG93ZWxsZ2Vub21pY3NsYWIvTmVidWxvc2EiKQogICAgaWYocmVxdWlyZShOZWJ1bG9zYSkpewogICAgICAgIHByaW50KCJOZWJ1bG9zYSBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIE5lYnVsb3NhIikKICAgIH0KfQoKIyMgbW9ub2NsZTMgdG8gY2FsY3VsYXRlIHBzZXVkb3RpbWU6CmlmKHJlcXVpcmUoIm1vbm9jbGUzIikpewogICAgcHJpbnQoIm1vbm9jbGUzIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoIlBsZWFzZSBpbnN0YWxsIG1vbm9jbGUzIChodHRwczovL2NvbGUtdHJhcG5lbGwtbGFiLmdpdGh1Yi5pby9tb25vY2xlMy9kb2NzL2luc3RhbGxhdGlvbi8pIikKfQoKIyMgc2V0IHRoZSBzZWVkIGZvciBib3RoIHRoZSBtaXh0dXJlIG1vZGVscyBhbmQgYWxzbyBmb3IgdGhlIHNhbXBsZSBmdW5jdGlvbiBsYXRlciBvbjoKc2V0LnNlZWQoLTkyNDk3KQpgYGAKCiMjIyBSZWFkIGluIHRoZSBEYXRhCgpzY3JlZW4gaGl0cwpgYGB7cn0KIyMgRURJVCAtIGNoYW5nZSB0aGlzIHRvIHRoZSBleGNlbCB0YWJsZSBvbmNlIHdlIGhhdmUgaXQgZmluYWxpemVkIGZvciB0aGUgc2NyZWVuCnNjcmVlbl9oaXRzIDwtIGMoIlBCQU5LQS0wNTE2MzAwIiwKIlBCQU5LQS0xMjE3NzAwIiwKIlBCQU5LQS0wNDA5MTAwIiwKIlBCQU5LQS0xMDM0MzAwIiwKIlBCQU5LQS0xNDM3NTAwIiwKIlBCQU5LQS0wODI3NTAwIiwKIlBCQU5LQS0wODI0MzAwIiwKIlBCQU5LQS0xNDI2OTAwIiwKIlBCQU5LQS0wMTA1MzAwIiwKIlBCQU5LQS0wOTIxMTAwIiwKIlBCQU5LQS0xMDAyNDAwIiwKIlBCQU5LQS0wODI5NDAwIiwKIlBCQU5LQS0xMzQ3MjAwIiwKIlBCQU5LQS0wODI4MDAwIiwKIlBCQU5LQS0wOTAyMzAwIiwKIlBCQU5LQS0xNDE4MTAwIiwKIlBCQU5LQS0xNDM1MjAwIiwKIlBCQU5LQS0xNDU0ODAwIiwKIlBCQU5LQS0wNzEyMzAwIiwKIlBCQU5LQS0wNDEwNTAwIiwKIlBCQU5LQS0xMTQ0ODAwIiwKIlBCQU5LQS0xMjMxNjAwIiwKIlBCQU5LQS0wNTAzMjAwIiwKIlBCQU5LQS0wMzA4OTAwIiwKIlBCQU5LQS0xMjE0NzAwIiwKIlBCQU5LQS0wNzA5OTAwIiwKIlBCQU5LQS0wMzExOTAwIiwKIlBCQU5LQS0wNzE2NTAwIiwKIlBCQU5LQS0xNDQ3OTAwIiwKIlBCQU5LQS0wMTAyMjAwIiwKIlBCQU5LQS0wNzEzNTAwIiwKIlBCQU5LQS0wMTAyNDAwIiwKIlBCQU5LQS0xMzAyNzAwIiwKIlBCQU5LQS0xMjM1OTAwIiwKIlBCQU5LQS0wNDAxMTAwIiwKIlBCQU5LQS0wNDEzNDAwIiwKIlBCQU5LQS0xMTI2OTAwIiwKIlBCQU5LQS0xNDI1OTAwIiwKIlBCQU5LQS0wNDE4MzAwIiwKIlBCQU5LQS0xNDY0NjAwIiwKIlBCQU5LQS0wODA2MDAwIikKYGBgCgpSZWFkIGluIGdlbmUgYW5ub3RhdGlvbnMKYGBge3J9CmdlbmVfYW5ub3RhdGlvbnMgPC0gcmVhZC50YWJsZSgiLi4vZGF0YS9SZWZlcmVuY2UvR2VuZXNCeVRheG9uX1N1bW1hcnkuY3N2IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkKZGltKGdlbmVfYW5ub3RhdGlvbnMpCgojIyBjb252ZXJ0IF8gdG8gLQpnZW5lX2Fubm90YXRpb25zJEdlbmUuSUQgPC0gZ3N1YigiXyIsICItIiwgZ2VuZV9hbm5vdGF0aW9ucyRHZW5lLklEKQpgYGAKCmxvYWQgaW4gZGF0YXNldHMKYGBge3J9CiMjIGxvYWQgdGhlIDEwWCBkYXRhc2V0CnBiX3NleF9maWx0ZXJlZCA8LSByZWFkUkRTKCIuLi9kYXRhX3RvX2V4cG9ydC9wYl9zZXhfZmlsdGVyZWQuUkRTIikKIyMgbG9hZCB0aGUgU1MyIGRhdGFzZXQKc3MyX211dGFudHNfZmluYWwgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvc3MyX211dGFudHNfZmluYWwuUkRTIikKCiMjIGluc3BlY3QKcGFzdGUoIjEweCBkYXRhc2V0IikKcGJfc2V4X2ZpbHRlcmVkCnBhc3RlKCJTbWFydC1zZXEyIGRhdGFzZXQiKQpzczJfbXV0YW50c19maW5hbApwYXN0ZSgiVGhlIGNvbXBvc2l0aW9uIG9mIHRoZSBTbWFydC1zZXEyIGRhdGFzZXQgaXM6IikKdGFibGUoc3MyX211dGFudHNfZmluYWxAbWV0YS5kYXRhJGdlbm90eXBlKQpgYGAKCiMgMy4gTWVyZ2luZyB0aGUgU21hcnQtc2VxMiBhbmQgMTBYIERhdGEgey50YWJzZXR9CgojIyMgUHJlcGFyZSBkYXRhCgpgYGB7ciBpbnRlZ3JhdGlvbiAxMHggc2V0dXB9CiMjIGV4dHJhY3QgMTB4IGRhdGEKdGVueF81a19jb3VudHMgPC0gYXMubWF0cml4KHBiX3NleF9maWx0ZXJlZEBhc3NheXMkUk5BQGNvdW50cykKdGVueF81a19waGVubyA8LSBwYl9zZXhfZmlsdGVyZWRAbWV0YS5kYXRhCgojIyBDcmVhdGUgZnJlc2ggb2JqZWN0CnRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZSA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gdGVueF81a19jb3VudHMsIG1ldGEuZGF0YSA9IHRlbnhfNWtfcGhlbm8sIG1pbi5jZWxscyA9IDAsIG1pbi5mZWF0dXJlcyA9IDAsIHByb2plY3QgPSAiR0NTS08iKQoKIyMgYWRkIGV4cGVyaW1lbnQgbWV0YSBkYXRhCnRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZUBtZXRhLmRhdGEkZXhwZXJpbWVudCA8LSAidGVueF81ayIKCiMjIGluc3BlY3QKdGVueF81a19jb3VudHNfdG9faW50ZWdyYXRlCmBgYAoKV2UgbmVlZCB0byBtYWtlIHN1cmUgdGhlIG11dGFudCBkYXRhIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgMTBYIGRhdGEuIHRoZSAxMFggZGF0YSBoYXMgZmV3ZXIgZ2VuZXMgcmVwcmVzZW50ZWQgc28gd2UgbmVlZCB0byBmaW5kIHRoZSBpbnRlcnNlY3Qgb2YgdGhlIHR3byBiZWZvcmUgaW50ZWdyYXRpb24uCmBgYHtyIGludGVncmF0aW9uIHNzMiBzZXR1cH0KIyMgZXh0cmFjdCBTUzIgZGF0YSAKbXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24gPC0gYXMubWF0cml4KHNzMl9tdXRhbnRzX2ZpbmFsQGFzc2F5cyRSTkFAY291bnRzKQptdXRhbnRfcGhlbm9fZm9yX2ludGVncmF0aW9uIDwtIHNzMl9tdXRhbnRzX2ZpbmFsQG1ldGEuZGF0YQoKIyMgY2hhbmdlIGNvdW50cyBzbyB0aGUgOnJSTkEgYW5kIDp0Uk5BIGFyZSBub3QgdGhlcmU6CnJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSA8LSBnc3ViKCI6bmNSTkEiLCAiIiwgZ3N1YigiOnJSTkEiLCAiIiwgZ3N1YigiOnRSTkEiLCAiIiwgcm93bmFtZXMobXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pKSkpCgojIyBjaGFuZ2UgdGhlIGdlbmUgbmFtZXMgc28gdGhhdCB0aGV5IGFyZSAtIHJhdGhlciB0aGFuIF86CnJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSA8LSBnc3ViKCJfIiwgIi0iLCByb3duYW1lcyhtdXRhbnRfY291bnRzX2Zvcl9pbnRlZ3JhdGlvbikpCgojIyBjYWxjdWxhdGUgaG93IG1hbnkgb2YgdGhlIGdlbmVzIG92ZXJsYXAgLSAxMHggZG9lcyBzdGFydCBvdXQgd2l0aCA1MDk4IHZzIDUyNDUKZ2VuZXNfaW5fdGVueF9kYXRhc2V0IDwtIGludGVyc2VjdChyb3duYW1lcyh0ZW54XzVrX2NvdW50cyksIHJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSkKIyMgcHJpbnQgbnVtYmVyIG9mIGdlbmVzIHRoYXQgb3ZlcmxhcApkaW0obXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pCiMjIHN1YnNldCB0aGUgbXV0YW50IGNvdW50cyB0byBjb250YWluIG9ubHkgMTB4IGdlbmVzCm11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uIDwtIG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uW3doaWNoKHJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSAlaW4lIGdlbmVzX2luX3RlbnhfZGF0YXNldCksIF0KIyMgcHJpbnQgcmVzdWx0IG9mIGdlbmVzIHRoYXQgb3ZlcmxhcApkaW0obXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pCgojIyBtYWtlIFNldXJhdCBvYmplY3Q6CkdDU0tPX211dGFudHMgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uLCBtZXRhLmRhdGEgPSBtdXRhbnRfcGhlbm9fZm9yX2ludGVncmF0aW9uLCBtaW4uY2VsbHMgPSAwLCBtaW4uZmVhdHVyZXMgPSAwLCBwcm9qZWN0ID0gIkdDU0tPIikKCiMjIGFkZCBleHBlcmltZW50IG1ldGEgZGF0YQpHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YSRleHBlcmltZW50IDwtICJtdXRhbnRzIgoKIyMgaW5zcGVjdApHQ1NLT19tdXRhbnRzCmBgYAoKYGBge3J9CiMjIGRvdWJsZSBjaGVjayB0aGF0IHRoaXMgaXMgdGhlIHNhbWUgbnVtYmVyIG9mIGdlbmVzCiMjIHN1YnNldCBjb3VudHMgc28gdGhhdCBvbmx5IGdlbmVzIHJlcHJlc2VudGVkIGluIHRoZSBvdGhlciB0d28gb2JqZWN0cyBhcmUgdGhlcmU6Cmxlbmd0aChpbnRlcnNlY3Qocm93bmFtZXModGVueF81a19jb3VudHMpLCByb3duYW1lcyhtdXRhbnRfY291bnRzX2Zvcl9pbnRlZ3JhdGlvbikpKQpgYGAKCklNUE9SVEFOVCAtIHRoaXMgbmV4dCBzdGVwIGlzIGRpZmZlcmVudCB0byBHQ1NLT19tZXJnZSBhcyBpdCBzdWJzZXRzIHRoZSBzbWFydC1zZXEyIGRhdGEgaW50byB3aWxkLXR5cGUgb25seS4gCmBgYHtyfQojIyBzdWJzZXQgd3Qgb24gc3MyIGRhdGE6CnNzMl93dF9jZWxscyA8LSByb3duYW1lcyhHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YVtHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YSRnZW5vdHlwZSA9PSAiV1QiLCBdKQpHQ1NLT19tdXRhbnRzX3d0b25seSA8LSBzdWJzZXQoR0NTS09fbXV0YW50cywgY2VsbHMgPSBzczJfd3RfY2VsbHMpCmBgYAoKY3JlYXRlIGxpc3QgYW5kIG5vcm1hbGlzZToKYGBge3IgaW50ZWdyYXRpb24gbm9ybWFsaXNlfQojIyBtYWtlIGxpc3QKdGVueC5qdXN0d3QubGlzdCA8LSBsaXN0KHRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZSwgR0NTS09fbXV0YW50c193dG9ubHkpCgojIyBwcmVwYXJlIGRhdGEKZm9yIChpIGluIDE6bGVuZ3RoKHRlbnguanVzdHd0Lmxpc3QpKSB7CiAgICB0ZW54Lmp1c3R3dC5saXN0W1tpXV0gPC0gTm9ybWFsaXplRGF0YSh0ZW54Lmp1c3R3dC5saXN0W1tpXV0sIHZlcmJvc2UgPSBGQUxTRSkKICAgIHRlbnguanVzdHd0Lmxpc3RbW2ldXSA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyh0ZW54Lmp1c3R3dC5saXN0W1tpXV0sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgCiAgICAgICAgbmZlYXR1cmVzID0gMjAwMCwgdmVyYm9zZSA9IEZBTFNFKQogICAgYWxsLmdlbmVzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0Lmxpc3RbW2ldXSkKICAgIHRlbnguanVzdHd0Lmxpc3RbW2ldXSA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QubGlzdFtbaV1dLCBmZWF0dXJlcyA9IGFsbC5nZW5lcykKfQpgYGAKCiMjIyBJbnRlZ3JhdGUgb2JqZWN0cwoKYGBge3IgaW50ZWdyYXRpb259CiMjIEZpbmQgYW5jaG9ycwp0ZW54Lmp1c3R3dC5hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSB0ZW54Lmp1c3R3dC5saXN0LCBkaW1zID0gMToyMSwgdmVyYm9zZSA9IEZBTFNFKQoKIyMgSW50ZWdyYXRlIGRhdGEKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IHRlbnguanVzdHd0LmFuY2hvcnMsIGRpbXMgPSAxOjIxLCB2ZXJib3NlID0gRkFMU0UsIGZlYXR1cmVzLnRvLmludGVncmF0ZSA9IGdlbmVzX2luX3RlbnhfZGF0YXNldCkKYGBgCgojIDQuIERpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiB7LnRhYnNldH0KCiMjIyBQQ0EKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gNX0KIyMgTWFrZSB0aGUgZGVmYXVsdCBhc3NheSBpbnRlZ3JhdGVkCkRlZmF1bHRBc3NheSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKSA8LSAiaW50ZWdyYXRlZCIKCiMjIFJ1biB0aGUgc3RhbmRhcmQgd29ya2Zsb3cgZm9yIHZpc3VhbGl6YXRpb24gYW5kIGNsdXN0ZXJpbmcKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgdmVyYm9zZSA9IEZBTFNFKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIFJ1blBDQSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBucGNzID0gMzAsIHZlcmJvc2UgPSBGQUxTRSkKCiMjIGluc3BlY3QgUENzCkVsYm93UGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBuZGltcyA9IDMwLCByZWR1Y3Rpb24gPSAicGNhIikKYGBgCgojIyMgT3B0aW1pc2VkIFVNQVAKQWZ0ZXIgb3B0aW1pc2F0aW9uLCB0aGUgZm9sbG93aW5nIFVNQVAgY2FuIGJlIGNhbGN1bGF0ZWQ6CmBgYHtyIHVtYXAgcnVuIDIsIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSA3fQojIyBSdW4gb3B0aW1pc2VkIFVNQVAKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBSdW5VTUFQKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToxMCwgbi5uZWlnaGJvcnMgPSA1MCwgc2VlZC51c2UgPSAxMjM0LCBtaW4uZGlzdCA9IDAuNCwgcmVwdWxzaW9uLnN0cmVuZ3RoID0gMC4wMywgbG9jYWwuY29ubmVjdGl2aXR5ID0gMTUwKQpgYGAKCmBgYHtyIHVtYXAgdmlzdWFsaXNlIDJ9CiMjIHBsb3QKZHAxIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IEZBTFNFLCBwdC5zaXplID0gMC4wNSwgZGltcyA9IGMoMSwyKSwgc3BsaXQuYnkgPSAiZXhwZXJpbWVudCIpICsgCiAgIyMgZml4IHRoZSBheGlzCiAgY29vcmRfZml4ZWQoKSAjKyAKICAjIyByZXZlcnNlIHRoZSBzY2FsZQogICNzY2FsZV95X3JldmVyc2UoKQoKIyMgdmlldwpkcDEKYGBgCgpNYWtlIGZpbmFsIHBsb3RzOgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KCiMjIHNwbGl0IHNldXJhdCBvYmplY3QgdXAKb2IubGlzdCA8LSBTcGxpdE9iamVjdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBzcGxpdC5ieSA9ICJleHBlcmltZW50IikKCiMjIG1ha2UgcGxvdHMgZm9yIGVhY2ggb2JqZWN0CnBsb3QubGlzdCA8LSBsYXBwbHkoWCA9IG9iLmxpc3QsIEZVTiA9IGZ1bmN0aW9uKHgpIHsKICAgIERpbVBsb3QoeCwgZGltcyA9IGMoMSwyKSwgcHQuc2l6ZSA9IDEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKQp9KQoKY29tcG9zaXRpb25fdW1hcF8xMHggPC0gcGxvdC5saXN0JGB0ZW54XzVrYCArIAogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKHJlcGxpY2F0ZSg0NSwgIiM5OTk5OTkiKSkpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIjEweCAod2lsZC10eXBlKSIpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkKCmNvbXBvc2l0aW9uX3VtYXBfc3MyIDwtIHBsb3QubGlzdCRtdXRhbnRzICsKICBjb29yZF9maXhlZCgpICsKICB0aGVtZV92b2lkKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyhyZXBsaWNhdGUoNDYsICIjOTk5OTk5IikpKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTbWFydC1zZXEyICh3aWxkLXR5cGUpIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKQoKY29tcG9zaXRpb25fdW1hcCA8LSBjb21wb3NpdGlvbl91bWFwXzEweCArIGNvbXBvc2l0aW9uX3VtYXBfc3MyIAoKY29tcG9zaXRpb25fdW1hcApgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9jb21wb3NpdGlvbl91bWFwLnBuZyIsIHBsb3QgPSBjb21wb3NpdGlvbl91bWFwLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjAsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCmBgYHtyfQojIyBtYWtlIHBsb3RzCiMjIGhvbyBkYXRhc2V0IGNvcnJlbGF0aW9uClVNQVBfaG9vIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcHQuc2l6ZSA9IDAuMSwgZ3JvdXAuYnkgPSAiUHJlZGljdGlvbi5TcGVhcm1hbi4iLCBkaW1zID0gYygxLDIpKSArCiAgY29vcmRfZml4ZWQoKSArIAogIHRoZW1lX3ZvaWQoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJIb28gUHJlZGljdGVkIFRpbWVwb2ludCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBpbmZlcm5vKDEyKSkgICsKICBsYWJzKGNvbG91ciA9ICJob3VyIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKIyMgYXAyZyB0aW1lY291cnNlIGluIHRoaXMgcGFwZXIgY29ycmVsYXRpb24KVU1BUF9rYXNpYSA8LSBEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIHB0LnNpemUgPSAwLjEsIGdyb3VwLmJ5ID0gIlByZWRpY3Rpb24uU3BlYXJtYW4uX0thc2lhIiwgZGltcyA9IGMoMSwyKSkgKwogIGNvb3JkX2ZpeGVkKCkgKyAKICB0aGVtZV92b2lkKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiQVAyRyBUaW1lY291cnNlIFByZWRpY3RlZCBUaW1lcG9pbnQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gaW5mZXJubygxMCkpICArCiAgbGFicyhjb2xvdXIgPSAiaG91ciIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwKSkKCiMjIGNvbWJpbmUKdW1hcF9idWxrIDwtIHdyYXBfcGxvdHMoVU1BUF9ob28sIFVNQVBfa2FzaWEsIG5jb2wgPSAyKQoKIyMgcHJpbnQKdW1hcF9idWxrCmBgYAoKIyA1LiBDbHVzdGVyaW5nIHsudGFic2V0fSAKCiMjIyBHZW5lcmF0ZSBjbHVzdGVycwoKYGBge3J9CiMjIGdlbmVyYXRlIG5ldyBjbHVzdGVycyBhdCBsb3cgcmVzb2x1dGlvbgp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEZpbmROZWlnaGJvcnModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IDE6MTksIHJlZHVjdGlvbiA9ICJwY2EiKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEZpbmRDbHVzdGVycyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCByZXNvbHV0aW9uID0gMiwgcmFuZG9tLnNlZWQgPSA0MiwgYWxnb3JpdGhtID0gMikKYGBgCgojIyMgdmlzdWFsaXNlIGNsdXN0ZXJzCgpgYGB7cn0KRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUsIHJlcGVsID0gRkFMU0UsIGxhYmVsID0gVFJVRSkKYGBgCgpNYWtlIGluZGl2aWR1YWwgcGxvdHMgaGlnaGxpZ2h0aW5nIHdoZXJlIGNlbGxzIGluIGVhY2ggY2x1c3RlciBmYWxsCmBgYHtyLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMjIGZvciBsb29wIHdoaWNoIHRha2VzIGVhY2ggY2x1c3RlciBhbmQgbWFrZXMgYSBsaXN0IG9mIGNlbGxzIGFuZCB0aGVuIHBsb3RzIGEgaGlnaGxpZ2h0ZWQgcGxvdCBhbmQgYWRkcyBpdCB0byBhIGxpc3QKCiMjIG1ha2UgYSBibGFuayBsaXN0Cmxpc3RfVU1BUHNfYnlfY2x1c3RlciA8LSB2ZWN0b3IobW9kZSA9ICJsaXN0IiwgbGVuZ3RoID0gbGVuZ3RoKGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMikpKQoKIyMgZm9yIGxvb3AKZm9yKGkgaW4gc2VxX2Fsb25nKGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMikpKXsKICAjIyBtYWtlIGEgbGlzdCBvZiBjZWxscwogIGxpc3Rfb2ZfY2VsbHMgPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbd2hpY2godGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkaW50ZWdyYXRlZF9zbm5fcmVzLjIgPT0gbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJGludGVncmF0ZWRfc25uX3Jlcy4yKVtpXSksIF0pCiAgdW1hcF9wbG90IDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbGFiZWwgPSBGQUxTRSwgcmVwZWwgPSBUUlVFLCBwdC5zaXplID0gMC4xLCBjZWxscy5oaWdobGlnaHQgPSBsaXN0X29mX2NlbGxzLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIpICsKICAgICMjIGZpeCBjb29yZGluYXRlcwogICAgY29vcmRfZml4ZWQoKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiI0QzRDNEMyIsICIjMUQxNTY0IikpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJjbHVzdGVyIiwgbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJGludGVncmF0ZWRfc25uX3Jlcy4yKVtpXSkpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKICAjIyBhZGQgdG8gdGhlIGxpc3QKICBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbW2ldXSA8LSB1bWFwX3Bsb3QKfQoKIyMgY2hlY2sgbnVtYmVyIG9mIGNsdXN0ZXJzCmxlbmd0aChsaXN0X1VNQVBzX2J5X2NsdXN0ZXIpCmBgYAoKcGxvdApgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyMgdGhpcyBmdW5jdGlvbiB3cml0ZXMgdGhlIG5leHQgYml0IG9mIGNvZGUgZm9yIHlvdQojIyBwdXQgaXQgaW50byB0aGUgY29uc29sZSBhbmQgcGFzdGUgdGhlIHJlc3BvbnNlCiNwbG90eSA8LSBjKCkKI2ZvcihpIGluIHNlcV9hbG9uZyhsZXZlbHModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzKSkpewojICBwbG90eSA8LSBwYXN0ZTAocGxvdHksICJsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWyIsIGksICJdXSIsICIgKyAiKQojfQoKIyMgcGxvdApsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzFdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1szXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzRdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzddXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbOF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzExXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE0XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE1XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE3XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE4XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIxXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzI0XV0KYGBgCgojIyMgRmluZCBNYXJrZXJzCgpgYGB7cn0KRGVmYXVsdEFzc2F5KHRlbnguanVzdHd0LmludGVncmF0ZWQpIDwtICJSTkEiCiMgZmluZCBtYXJrZXJzIGZvciBldmVyeSBjbHVzdGVyIGNvbXBhcmVkIHRvIGFsbCByZW1haW5pbmcgY2VsbHMsIHJlcG9ydCBvbmx5IHRoZSBwb3NpdGl2ZSBvbmVzCnBiLm1hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgbG9nZmMudGhyZXNob2xkID0gMC4yNSkKcGIubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSA1LCB3dCA9IGF2Z19sb2dGQykKYGBgCgpgYGB7ciwgUi5vcHRpb25zID0gbGlzdCh3aWR0aCA9IDMwMCl9Cm1hcmtlcnNfc3Vic2V0IDwtIHBiLm1hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSB0b3BfbihuID0gMjAsIHd0ID0gYXZnX2xvZ0ZDKQptYXJrZXJzX3N1YnNldF9hbm5vdGF0ZWQgPC0gbWVyZ2UobWFya2Vyc19zdWJzZXQsIGdlbmVfYW5ub3RhdGlvbnMsICBieS54ID0gImdlbmUiLCBieS55ID0gIkdlbmUuSUQiLCBhbGwgPSBGQUxTRSkKbWFya2Vyc19zdWJzZXRfYW5ub3RhdGVkClZpZXcobWFya2Vyc19zdWJzZXRfYW5ub3RhdGVkKQpgYGAKCiMjIyB2aXN1YWxpc2UgbWFya2VycwoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMjIGdldCB0aGUgdG9wIDEwIGZvciBlYWNoIGNsdXN0ZXIKdG9wMTAgPC0gcGIubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSAxMCwgd3QgPSBhdmdfbG9nRkMpCgojIyBzY2FsZSBkYXRhIGlzIG1pc3NpbmcgLSBidXQgb3JpZ2luYWwgZGZzIGhhdmUgc2NhbGUuZGF0YQojIGRmX3NjYWxlZCA8LSBhcy5tYXRyaXgodHJhbnNmb3JtKG1lcmdlKGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QubGlzdFtbMV1dQGFzc2F5cyRSTkFAc2NhbGUuZGF0YSksIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QubGlzdFtbMl1dQGFzc2F5cyRSTkFAc2NhbGUuZGF0YSksIGJ5ID0gMCwgYWxsPUZBTFNFKSwgcm93Lm5hbWVzPVJvdy5uYW1lcywgUm93Lm5hbWVzPU5VTEwpKQojIHRlbnguanVzdHd0LmludGVncmF0ZWRAYXNzYXlzJFJOQUBzY2FsZS5kYXRhIDwtIGRmX3NjYWxlZAoKIyMgc2NhbGUgZGF0YSBpbiBSTkEgc2xvdAphbGwuZ2VuZXMgPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZCkKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgdmFycy50by5yZWdyZXNzID0gJ2V4cGVyaW1lbnQnLCBmZWF0dXJlcyA9IGFsbC5nZW5lcykKCiMjIGhlYXRtYXAKRG9IZWF0bWFwKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gdG9wMTAkZ2VuZSkgKyBOb0xlZ2VuZCgpCmBgYAoKIyA2LiBEZWZpbmUgQ2x1c3RlciBJZGVudGl0aWVzIHsudGFic2V0fSAKCiMjIyBEb3duc2FtcGxpbmcKYGBge3J9CiMgIyMgY2hlY2sgbnVtYmVyIG9mIGNlbGxzIGluIGVhY2ggY2x1c3RlcgojIGRmX2NsdXN0ZXJzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkaW50ZWdyYXRlZF9zbm5fcmVzLjIpKQojIHBsb3QoZGZfY2x1c3RlcnMpCiMgCiMgIyMgZG93bnNhbXBsZSB1c2luZyBhcHByb3ByaWF0ZSBtZXRyaWNzCiMgdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5kb3duc2FtcGxlZCA8LSBzdWJzZXQodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZG93bnNhbXBsZSA9IDEwMCkKIyAgIAojICMjIGluc3BlY3QgcGxvdAojIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQuZG93bnNhbXBsZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM3NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiMgICB0aGVtZV92b2lkKCkgKyAKIyAgIGxhYnModGl0bGUgPSBwYXN0ZSgiQVAyRyAoQ29tbWl0bWVudCkiKSkgKyAKIyAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAojICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKYGBgCgojIyMgTWFya2VyIEdlbmVzCgp1c2VmdWwgdG9vbHMgZm9yIGFsbCBwbG90cwpgYGB7cn0KIyMgZGVmaW5lIG1hbGUgYW5kIGZlbWFsZSBzeW1ib2wKZmVtYWxlX3N5bWJvbCA8LSBpbnRUb1V0ZjgoOTc5MikKbWFsZV9zeW1ib2wgPC0gaW50VG9VdGY4KDk3OTQpCgojIyBkZWZpbmUgY29sb3VyIHBhbAptYXJrZXJfZ2VuZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0QzRDNEMyIsICIjMUQxNTY0IikpKDUwKQpgYGAKCiMjIyMgRXhwcmVzc2lvbiAtIGN1dG9mZnMgLSBwdXJwbGUKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTUsIGZpZy53aWR0aCA9IDE1fQoKbWFya2VyX2dlbmVfcGxvdF9DQ1AyIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTEzMTk1MDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKGNjcDIpfihGZW1hbGUpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X01HMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTYxMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZzEpfihNYWxlKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X0FQMkcgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNzUwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoYXAyZyl+KENvbW1pdG1lbnQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X01TUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDgzMTAwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMobXNwMSl+KFNjaGl6b250KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9NU1A4IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTExMDIyMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1zcDgpfihBc2V4dWFsKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9TQlAxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTExMDEzMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoU0JQMSl+KFJpbmcpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X0ZBTUIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDcyMjYwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmYW0tYjIpfihSaW5nKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9IU1A3MCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDcxMTkwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKGhzcDcwKX4oTGluZX5SZXBvcnRlcikpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCiMgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKIyMgcGxvdAojIyBjb3dwbG90IG1ldGhvZAptYXJrZXJfZ2VuZV9wbG90X2FsbCA8LSBwbG90X2dyaWQobWFya2VyX2dlbmVfcGxvdF9GQU1CLCBtYXJrZXJfZ2VuZV9wbG90X01TUDgsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQMSwgbWFya2VyX2dlbmVfcGxvdF9BUDJHLCBtYXJrZXJfZ2VuZV9wbG90X0NDUDIsIG1hcmtlcl9nZW5lX3Bsb3RfTUcxLCBtYXJrZXJfZ2VuZV9wbG90X0hTUDcwLCBucm93PTMpCgptYXJrZXJfZ2VuZV9wbG90X2FsbApgYGAKCiMjIyBNdXRhbnQgR2VuZXMKCiMjIyMgRXhwcmVzc2lvbiAtIHdpdGggY3V0b2ZmcwoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1ENCAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENSAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQzCiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTExNDQ4MDAgICAgICAgIEdDU0tPLTI4ICBGRDUKCgptYXJrZXJfZ2VuZV9wbG90X2ZkMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0xNDE4MTAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZmQzKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X21kNCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wMTAyNDAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAjIyBhZGQgc2V4IHN5bWJvbHMKICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X21kNSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wNzE2NTAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1kNSkpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpIAogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9mZDQgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNTIwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZmQ0KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkgCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X2ZkMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wOTAyMzAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmZDIpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICMgKyBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9tZDMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDQxMzQwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDMpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X2dkMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA4MjgwMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZ2QxKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKICAgICAgICAgICAgICAgICAgICAgICAjIyBhZGQgc2V4IHN5bWJvbHMKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfbWQxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTEzMDI3MDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDEpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9tZDIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTE0NDc5MDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDIpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9mZDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ1NDgwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmZDEpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKIyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKQojIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZSA8LSB3cmFwX3Bsb3RzKG1hcmtlcl9nZW5lX3Bsb3RfZ2QxICwgbWFya2VyX2dlbmVfcGxvdF9tZDEgLCBtYXJrZXJfZ2VuZV9wbG90X21kMiAsIG1hcmtlcl9nZW5lX3Bsb3RfbWQzICwgbWFya2VyX2dlbmVfcGxvdF9tZDQgLCBtYXJrZXJfZ2VuZV9wbG90X21kNSAsIG1hcmtlcl9nZW5lX3Bsb3RfZmQxICwgbWFya2VyX2dlbmVfcGxvdF9mZDIgLCBtYXJrZXJfZ2VuZV9wbG90X2ZkMyAsIG1hcmtlcl9nZW5lX3Bsb3RfZmQ0LCBuY29sID0gNCkKICAgICAgICAgICAKIyMgcHJpbnQKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1EMyAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENCAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQ1CiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTExNDQ4MDAgICAgICAgIEdDU0tPLTI4ICBGRDUKCgptYXJrZXJfZ2VuZV9wbG90XzE3IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0MTgxMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wMTAyNDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMyIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzE5IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA3MTY1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjAgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNTIwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wOTAyMzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkMiIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzEwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTM0MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wODI4MDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X29vbSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xMzAyNzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzI5IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0NDc5MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ1NDgwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlIDwtIHdyYXBfcGxvdHMobWFya2VyX2dlbmVfcGxvdF8xNyAsIG1hcmtlcl9nZW5lX3Bsb3RfMiAsIG1hcmtlcl9nZW5lX3Bsb3RfMTkgLCBtYXJrZXJfZ2VuZV9wbG90XzIwICwgbWFya2VyX2dlbmVfcGxvdF8xMyAsIG1hcmtlcl9nZW5lX3Bsb3RfMTAgLCBtYXJrZXJfZ2VuZV9wbG90XzMgLCBtYXJrZXJfZ2VuZV9wbG90X29vbSAsIG1hcmtlcl9nZW5lX3Bsb3RfMjkgLCBtYXJrZXJfZ2VuZV9wbG90XzIxICwgbmNvbCA9IDQpCiAgICAgICAgICAgCiMjIHByaW50Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZQpgYGAKCgoKIyA3LiBQc2V1ZG90aW1lIG9uIGFsbCBjZWxscyB7LnRhYnNldH0KCiMjIyBQc2V1ZG90aW1lIGNhbGN1bGF0aW9uCgpgYGB7cn0KIyMgZXh0cmFjdCBkYXRhIGZyb20gU2V1cmF0CnNldXJhdC5vYmplY3QuYWxsIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWQKIyBjb3VudHMKZGF0YSA8LSBhcyhhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKHNldXJhdC5vYmplY3QuYWxsLCBhc3NheSA9ICJpbnRlZ3JhdGVkIiwgc2xvdCA9ICJkYXRhIikpLCAnc3BhcnNlTWF0cml4JykKIyBtZXRhIGRhdGEKcGQgPC0gZGF0YS5mcmFtZShzZXVyYXQub2JqZWN0LmFsbEBtZXRhLmRhdGEpCgojIyBrZWVwIG9ubHkgdGhlIGNvbHVtbnMgdGhhdCBhcmUgcmVsZXZhbnQKI3BEYXRhIDwtIHBkICU+JSBzZWxlY3Qob3JpZy5pZGVudCwgbkNvdW50X1JOQSwgbkZlYXR1cmVfUk5BKQojIyBhZGQgZ2VuZSBzaG9ydCBuYW1lCmZEYXRhIDwtIGRhdGEuZnJhbWUoZ2VuZV9zaG9ydF9uYW1lID0gcm93Lm5hbWVzKGRhdGEpLCByb3cubmFtZXMgPSByb3cubmFtZXMoZGF0YSkpCgojIyBDb25zdHJ1Y3QgbW9ub2NsZSBjZHMKbW9ub2NsZS5vYmplY3QuYWxsIDwtIG5ld19jZWxsX2RhdGFfc2V0KGV4cHJlc3Npb25fZGF0YSA9IGRhdGEsIGNlbGxfbWV0YWRhdGEgPSBwZCwgZ2VuZV9tZXRhZGF0YSA9IGZEYXRhKQojIyBwcmVwcm9jZXNzCm1vbm9jbGUub2JqZWN0LmFsbCA9IHByZXByb2Nlc3NfY2RzKG1vbm9jbGUub2JqZWN0LmFsbCwgbnVtX2RpbSA9IDEwMCwgbm9ybV9tZXRob2QgPSAibm9uZSIpCiMjIHBsb3QgdmFyaWFuY2UgZXhwbGFpbmVkIHBsb3QKI3Bsb3RfcGNfdmFyaWFuY2VfZXhwbGFpbmVkKG1vbm9jbGUub2JqZWN0LmFsbCkKIyMgbWFrZSBtb25vY2xlIFVNQVAKI21vbm9jbGUub2JqZWN0LmFsbCA9IHJlZHVjZV9kaW1lbnNpb24obW9ub2NsZS5vYmplY3QuYWxsLCByZWR1Y3Rpb25fbWV0aG9kID0gIlVNQVAiLCBwcmVwcm9jZXNzX21ldGhvZCA9ICJQQ0EiLCB1bWFwLm1ldHJpYyA9ICJldWNsaWRlYW4iLCB1bWFwLm5fbmVpZ2hib3JzID0gMjAsIHVtYXAubWluX2Rpc3QgPSAwLjUsIHZlcmJvc2UgPSBGQUxTRSkKI3Bsb3RfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsKQoKIyMgYWRkIFVNQVAgZnJvbSBTZXVyYXQKbW9ub2NsZS5vYmplY3QuYWxsQGludF9jb2xEYXRhQGxpc3REYXRhJHJlZHVjZWREaW1zQGxpc3REYXRhW1siVU1BUCJdXSA8LXNldXJhdC5vYmplY3QuYWxsQHJlZHVjdGlvbnNbWyJ1bWFwIl1dQGNlbGwuZW1iZWRkaW5ncyAKcGxvdF9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwpCgojIyBjbHVzdGVyCm1vbm9jbGUub2JqZWN0LmFsbCA9IGNsdXN0ZXJfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsKQoKIyMgcGxvdCBjbHVzdGVycwpwbG90X2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCwgY29sb3JfY2VsbHNfYnk9InBhcnRpdGlvbiIsIGdyb3VwX2NlbGxzX2J5PSJwYXJ0aXRpb24iLCAgeCA9IDEsIHkgPSAyKQoKIyMgcmVkdWNlIHBhcnRpdGlvbnMgdG8gMQptb25vY2xlLm9iamVjdC5hbGxAY2x1c3RlcnMkVU1BUCRwYXJ0aXRpb25zW21vbm9jbGUub2JqZWN0LmFsbEBjbHVzdGVycyRVTUFQJHBhcnRpdGlvbnMgPT0gIjIiXSA8LSAiMSIKCiNtYXAgcHNldWRvdGltZQptb25vY2xlLm9iamVjdC5hbGwgPSBsZWFybl9ncmFwaChtb25vY2xlLm9iamVjdC5hbGwsIGxlYXJuX2dyYXBoX2NvbnRyb2w9bGlzdChuY2VudGVyPTU1MCwgbWluaW1hbF9icmFuY2hfbGVuID0gMTUpLCB1c2VfcGFydGl0aW9uID0gRkFMU0UpCgpwbG90X2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCwgY29sb3JfY2VsbHNfYnk9InBhcnRpdGlvbiIsIGdyb3VwX2NlbGxzX2J5PSJwYXJ0aXRpb24iLCAgeCA9IDEsIHkgPSAyKQoKIyMgYSBoZWxwZXIgZnVuY3Rpb24gdG8gaWRlbnRpZnkgdGhlIHJvb3QgcHJpbmNpcGFsIHBvaW50czoKIyMgbWFrZSBjbHVzdGVyIDIgdGhlIHJvb3QKIyBnZXRfZWFybGllc3RfcHJpbmNpcGFsX25vZGUgPC0gZnVuY3Rpb24oY2RzLCB0aW1lX2Jpbj0iNyIpewojICAgY2VsbF9pZHMgPC0gd2hpY2goY29sRGF0YShjZHMpWywgInNldXJhdF9jbHVzdGVycyJdID09IHRpbWVfYmluKQojICAgY2xvc2VzdF92ZXJ0ZXggPC0KIyAgIGNkc0BwcmluY2lwYWxfZ3JhcGhfYXV4W1siVU1BUCJdXSRwcl9ncmFwaF9jZWxsX3Byb2pfY2xvc2VzdF92ZXJ0ZXgKIyAgIGNsb3Nlc3RfdmVydGV4IDwtIGFzLm1hdHJpeChjbG9zZXN0X3ZlcnRleFtjb2xuYW1lcyhjZHMpLCBdKQojICAgcm9vdF9wcl9ub2RlcyA8LQojICAgaWdyYXBoOjpWKHByaW5jaXBhbF9ncmFwaChjZHMpW1siVU1BUCJdXSkkbmFtZVthcy5udW1lcmljKG5hbWVzCiMgICAod2hpY2gubWF4KHRhYmxlKGNsb3Nlc3RfdmVydGV4W2NlbGxfaWRzLF0pKSkpXQojICAgCiMgICByb290X3ByX25vZGVzCiMgfQoKIyMgY2FsY3VsYXRlIHBzZXVkb3RpbWUKI21vbm9jbGUub2JqZWN0LmFsbCA9IG9yZGVyX2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCwgcm9vdF9wcl9ub2Rlcz1nZXRfZWFybGllc3RfcHJpbmNpcGFsX25vZGUobW9ub2NsZS5vYmplY3QuYWxsKSkKbW9ub2NsZS5vYmplY3QuYWxsID0gb3JkZXJfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsKQojIyB1c2VkIDUgcG9pbnRzIGF0IHRoZSBiZWdpbm5pbmcKCgojIyBwbG90CnVtYXBfcHQgPC0gcGxvdF9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwsIGNvbG9yX2NlbGxzX2J5ID0gInBzZXVkb3RpbWUiLCBsYWJlbF9jZWxsX2dyb3Vwcz1GQUxTRSwgY2VsbF9zaXplID0gMSwgeCA9IDEsIHkgPSAyLCBsYWJlbF9icmFuY2hfcG9pbnRzPUZBTFNFLCBsYWJlbF9sZWF2ZXM9RkFMU0UsIGxhYmVsX2dyb3Vwc19ieV9jbHVzdGVyPUZBTFNFLCBsYWJlbF9yb290cyA9IEZBTFNFKSArCiAgY29vcmRfZml4ZWQoKSArCiAgdGhlbWVfdm9pZCgpICsKICBsYWJzKHRpdGxlID0gIiIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplPTIwKSwgbGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0IChzaXplPTIwKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArIAogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAxMCwgYmFyaGVpZ2h0ID0gMiwgdGl0bGUgPSAiUHNldWRvdGltZSIpKQoKIyMgdmlldyBwbG90CnVtYXBfcHQKCiMjIGhlbHAgd2FzIG9idGFpbmVkIGZyb20gaGVyZQojIyBodHRwczovL2dpdGh1Yi5jb20vc2F0aWphbGFiL3NldXJhdC9pc3N1ZXMvMTY1OApgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9VTUFQX3B0X3d0LnBuZyIsIHBsb3QgPSB1bWFwX3B0LCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjAsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMjIyBnZ2FuaW1uYXRlIEdJRiBvZiBwc2V1b2R0aW1lCgpgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoImdnYW5pbWF0ZSIpCmxpYnJhcnkoZ2dhbmltYXRlKQojaW5zdGFsbC5wYWNrYWdlcygiZ2lmc2tpIikKI2luc3RhbGwucGFja2FnZXMoImF2IikKI2xpYnJhcnkoZ2lmc2tpKQojbGlicmFyeShhdikKCiMjIG1ha2UgZGF0YWZyYW1lIGZvciBwbG90dGluZwojIyBleHRyYWN0IGRhdGEgZm9yIEdHcGxvdCB2ZXJzaW9uIG9mIHRoaXMKZGZfYW5pbWF0aW9uIDwtIGFzLmRhdGEuZnJhbWUobW9ub2NsZS5vYmplY3QuYWxsQGludF9jb2xEYXRhQGxpc3REYXRhJHJlZHVjZWREaW1zQGxpc3REYXRhW1siVU1BUCJdXSkKIyMgYWRkIHB0IHRvIHRoaXMgZGF0YSBmcmFtZToKcHRfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUocHNldWRvdGltZShtb25vY2xlLm9iamVjdC5hbGwsIHJlZHVjdGlvbl9tZXRob2QgPSAiVU1BUCIpKQpkZl9hbmltYXRpb24gPC0gbWVyZ2UoZGZfYW5pbWF0aW9uLCBwdF92YWx1ZXMsIGJ5PSJyb3cubmFtZXMiKSAKcm93bmFtZXMoZGZfYW5pbWF0aW9uKSA8LSBkZl9hbmltYXRpb24kUm93Lm5hbWVzCmNvbG5hbWVzKGRmX2FuaW1hdGlvbilbNF0gPC0gInB0IgoKIyMgbWFrZSB0aGUgc3RhdGljIHBsb3QKcCA8LSBnZ3Bsb3QoZGZfYW5pbWF0aW9uLCBhZXMoeCA9IFVNQVBfMSwgeSA9IFVNQVBfMiwgY29sb3VyID0gcHQpKSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV9jb2xvdXJfdmlyaWRpc19jKG9wdGlvbiA9ICJwbGFzbWEiKSArCiAgY29vcmRfZml4ZWQoKSArCiAgdGhlbWVfdm9pZCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiMjIHZpZXcgcGxvdApwbG90KHApCgojIyBtYWtlIGFuaW1hdGVkIHBsb3QKIyMgbWFrZSBhIGNhdGVnb3J5IGZvciBhbmltYXRpb24KI2RmX2FuaW1hdGlvbiRncm91cCA8LSBjdXQoZGZfYW5pbWF0aW9uJHB0LCAxNSkKCmFuaW0gPC0gcCArCiAgdHJhbnNpdGlvbl90aW1lKHB0KSArCiAgc2hhZG93X21hcmsoKQoKYW5pbWF0ZShhbmltLCBoZWlnaHQgPSAzLCB3aWR0aCA9IDMsIHVuaXRzID0gImluIiwgcmVzID0gMTUwLCBiZyA9ICd0cmFuc3BhcmVudCcpCgojIyB0byBjaGFuZ2UgdGhlIHJlc29sdXRpb24gLSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80OTA1ODU2Ny9kZWZpbmUtc2l6ZS1mb3ItZ2lmLWNyZWF0ZWQtYnktZ2dhbmltYXRlLWNoYW5nZS1kaW1lbnNpb24tcmVzb2x1dGlvbiAKYGBgClNhdmUgYW5pbWF0aW9uCmBgYHtyfQphbmltX3NhdmUoImFuaW1hdGVkX1VNQVBfdHJhbnNwYXJlbnRfYmdfd3QuZ2lmIiwgcGF0aCA9ICIuLi9pbWFnZXNfdG9fZXhwb3J0LyIpCmBgYAoKYGBge3J9CiMjIGV4dHJhY3QgcHQgdmFsdWVzCnB0X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHBzZXVkb3RpbWUobW9ub2NsZS5vYmplY3QuYWxsLCByZWR1Y3Rpb25fbWV0aG9kID0gIlVNQVAiKSkKCnRlbnguanVzdHd0LmludGVncmF0ZWQgPC0gQWRkTWV0YURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcHRfdmFsdWVzLCAib2xkX3B0X3ZhbHVlcyIpCmBgYAoKIyMjIyBEZWZpbmUgY2VsbCBpZGVudGl0aWVzIHdpdGggYnJhbmNoZXMKCkRlZmluZSBpZGVudGl0aWVzIG9mIGNlbGxzIAoKbWFsZQpgYGB7cn0KbW9ub2NsZS5vYmplY3RfbWFsZSA8LSBjaG9vc2VfZ3JhcGhfc2VnbWVudHMobW9ub2NsZS5vYmplY3QuYWxsKQpgYGAKZmVtYWxlCmBgYHtyfQptb25vY2xlLm9iamVjdF9mZW1hbGUgPC0gY2hvb3NlX2dyYXBoX3NlZ21lbnRzKG1vbm9jbGUub2JqZWN0LmFsbCkKYGBgCmJpcG90ZW50aWFsCmBgYHtyfQptb25vY2xlLm9iamVjdF9iaXBvdCA8LSBjaG9vc2VfZ3JhcGhfc2VnbWVudHMobW9ub2NsZS5vYmplY3QuYWxsKQpgYGAKYXNleHVhbCAocHJlLWJyYW5jaCkKYGBge3J9Cm1vbm9jbGUub2JqZWN0X2FzZXhfcHJlIDwtIGNob29zZV9ncmFwaF9zZWdtZW50cyhtb25vY2xlLm9iamVjdC5hbGwpCmBgYAphc2V4dWFsIGZhdGUKYGBge3J9Cm1vbm9jbGUub2JqZWN0X2FzZXhfZmF0ZSA8LSBjaG9vc2VfZ3JhcGhfc2VnbWVudHMobW9ub2NsZS5vYmplY3QuYWxsKQpgYGAKY2hlY2sKYGBge3J9CmRmX2ZyZXEgPC0gZGF0YS5mcmFtZSh0YWJsZShjKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X21hbGUpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9mZW1hbGUpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9iaXBvdCksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfcHJlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9mYXRlKSkpKQpwYXN0ZSgibnVtYmVyIG9mIGNlbGxzIGluIHNldXJhdCBvYmplY3QgaXMiLCBsZW5ndGgoY29sbmFtZXMobW9ub2NsZS5vYmplY3QuYWxsKSksICIuIFRoZSBudW1iZXIgb2YgY2VsbHMgc2VsZWN0ZWQgaGVyZSB3aXRoIGFuIGlkZW50aXRpdHkgaXMiLCBkaW0oZGZfZnJlcSlbMV0pCmRmX2ZyZXEgPC0gZGZfZnJlcVtkZl9mcmVxJEZyZXEgPiAxLCBdCmRmX2ZyZXEKYGBgCkluc3BlY3Qgd2hlcmUgdGhlc2UgbWlzc2luZyBjZWxscyBhcmU6CmBgYHtyfQojICclbmklJyA8LSBOZWdhdGUoJyVpbiUnKQojIAojIG5vdF9hc3NpZ25lZF9jZWxscyA8LSBjb2xuYW1lcyhtb25vY2xlLm9iamVjdC5hbGwpW2NvbG5hbWVzKG1vbm9jbGUub2JqZWN0LmFsbCkgJW5pJSBjKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X21hbGUpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9mZW1hbGUpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9iaXBvdCksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXgpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X2ZhdGUpKV0KIyAKIyBEaW1QbG90KHNldXJhdC5vYmplY3QsIHJlcGVsID0gVFJVRSwgbGFiZWwuc2l6ZSA9IDUsIHB0LnNpemUgPSAwLjUsIGNlbGxzLmhpZ2hsaWdodCA9IG5vdF9hc3NpZ25lZF9jZWxscywgZGltcyA9IGMoMiwxKSwgcmVkdWN0aW9uID0gIkRJTV9VTUFQIikgKwojICAgY29vcmRfZml4ZWQoKSArIAojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiNmNTRlMWUiKSkKYGBgCgpgYGB7cn0KIyMgY3JlYXRlIGFubm90YXRpb24gZGF0YWZyYW1lIGZyb20gdGhlc2UgcmVzdWx0czoKZGZfbW9ub2NsZV9zZXhlcyA8LSByYmluZChkYXRhLmZyYW1lKCJjZWxsX25hbWUiID0gY29sbmFtZXMobW9ub2NsZS5vYmplY3RfbWFsZSksICJzZXgiID0gcmVwKCJNYWxlIiwgbGVuZ3RoKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X21hbGUpKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoImNlbGxfbmFtZSIgPSBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9mZW1hbGUpLCAic2V4IiA9IHJlcCgiRmVtYWxlIiwgbGVuZ3RoKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2ZlbWFsZSkpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2JpcG90KSwgInNleCIgPSByZXAoIkJpcG90ZW50aWFsIiwgbGVuZ3RoKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2JpcG90KSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmZyYW1lKCJjZWxsX25hbWUiID0gY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9wcmUpLCAic2V4IiA9IHJlcCgiQXNleHVhbF9FYXJseSIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X3ByZSkpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfZmF0ZSksICJzZXgiID0gcmVwKCJBc2V4dWFsX0xhdGUiLCBsZW5ndGgoY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9mYXRlKSkpKQogICAgICAgICAgICAgICAgICAgICAgICAgICNkYXRhLmZyYW1lKCJjZWxsX25hbWUiID0gbm90X2Fzc2lnbmVkX2NlbGxzLCAic2V4IiA9IHJlcCgiVW5hc3NpZ25lZCIsIGxlbmd0aChub3RfYXNzaWduZWRfY2VsbHMpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICApCgpkaW0oZGZfbW9ub2NsZV9zZXhlcykKCiMjIG9yZGVyIGxpa2UgdGhlIG1ldGFkYXRhCmRmX21vbm9jbGVfc2V4ZXMgPC0gZGZfbW9ub2NsZV9zZXhlc1ttYXRjaChyb3duYW1lcyhtb25vY2xlLm9iamVjdC5hbGxAY29sRGF0YSksIGRmX21vbm9jbGVfc2V4ZXMkY2VsbF9uYW1lKSwgXQoKIyMgYWRkIHRoaXMgYmFjayBpbnRvIHRoZSBtb25vY2xlIG9iamVjdAptb25vY2xlLm9iamVjdC5hbGxAY29sRGF0YSRTZXhlc19tb25vY2xlIDwtIGRmX21vbm9jbGVfc2V4ZXMkc2V4CgojIyBhZGQgdGhpcyB0byB0aGUgc2V1cmF0IG9iamVjdApyb3duYW1lcyhkZl9tb25vY2xlX3NleGVzKSA8LSBkZl9tb25vY2xlX3NleGVzJGNlbGxfbmFtZQpkZl9tb25vY2xlX3NleGVzX3RvX2FkZF90b19zZXVyYXQgPC0gZGZfbW9ub2NsZV9zZXhlc1ssYygic2V4IiksIGRyb3AgPSBGQUxTRV0KdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBBZGRNZXRhRGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkZl9tb25vY2xlX3NleGVzX3RvX2FkZF90b19zZXVyYXQsIGNvbC5uYW1lID0gIm1vbm9jbGVfc2V4IikKYGBgCgoKCiMgOC4gUGxvdHMgey50YWJzZXR9CgptYWtlIGNvbXBvc2l0ZSBwc2V1ZG90aW1lL0lEIGZpZ3VyZQoKYGBge3J9CiMgMSA9IGJsdWUgLSAiIzAwNTJjNSIKIyAyID0gcmVkIC0gIiNhNTJiMWUiCiMgMyA9IGdyZWVuIC0gIiMwMTZjMDAiCiMgNCA9IHllbGxvdyAtICIjZmZlNDAwIgojcGFsX3NleCA8LSBjKCIjMDA1MmM1IiwiI2ZmZTQwMCIsICIjYTUyYjFlIiwgIiMwMTZjMDAiKQoKIyMgZXh0cmFjdCBwc2V1ZG90aW1lIG51bWJlcnMgYW5kIGlkZW50aXR5IG9mIGNlbGxzIHRvIGEgZGF0YWZyYW1lCmRmX3B0X2lkIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhWyxjKCJvbGRfcHRfdmFsdWVzIiwgIm1vbm9jbGVfc2V4IildCgojIyBpbnNwZWN0IHBvc3NpYmxlIHZhbHVlcwpsaXN0X29mX3NleGVzIDwtIG5hbWVzKHRhYmxlKGRmX3B0X2lkJG1vbm9jbGVfc2V4KSkKCiMjIG1ha2UgYSBuZXcgY29sdW1uCmRmX3B0X2lkJGNvbG91ciA8LSBOQQoKIyMgbWFrZSBjb2xvdXIgcmFtcHMKYXNleF9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0Q1RTNGNSIsICIjMDA1MmM1IikpCm1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIndoaXRlIiwgInllbGxvdyIsICIjMDE2YzAwIikpCmZlbWFsZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygieWVsbG93IiwgIiNhNTJiMWUiKSkKYmlwb3RfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIndoaXRlIiwgIiNmZmU0MDAiKSkKCiMjIHJlLWNsYXNzaWZ5IHRoZSBjZWxscyB0aGF0IGFyZSB1bmFzc2lnbmVkIGNlbGxzIHJlbW92ZWQgZnJvbSBzZXh1YWwgYnJhbmNoIGFib3ZlOgojZGZfcHRfaWRbd2hpY2gocm93bmFtZXMoZGZfcHRfaWQpICVpbiUgcmVtb3ZlX2NlbGxzKSwgXSRtb25vY2xlX3NleCA8LSAiQXNleHVhbCIKCiMjIGFzc2lnbiB2YWx1ZXMgdG8gZWFjaCBjbHVzdGVyCiMjIGhlbHAgaGVyZTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvOTk0NjYzMC9jb2xvdXItcG9pbnRzLWluLWEtcGxvdC1kaWZmZXJlbnRseS1kZXBlbmRpbmctb24tYS12ZWN0b3Itb2YtdmFsdWVzIApkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9FYXJseSIgfCBkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9MYXRlIiwgXSRjb2xvdXIgPC0gYXNleF9yYW1wKDEwMClbYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKV0KCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJNYWxlIiwgXSRjb2xvdXIgPC0gbWFsZV9yYW1wKDEwMClbYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIk1hbGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSldCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiRmVtYWxlIiwgXSRjb2xvdXIgPC0gZmVtYWxlX3JhbXAoMTAwKVthcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiRmVtYWxlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpXQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkJpcG90ZW50aWFsIiwgXSRjb2xvdXIgPC0gYmlwb3RfcmFtcCgxMDApW2FzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKV0KCiMjIGNoZWNrIGV2ZXJ5dGhpbmcgaGFzIGEgdmFsdWUKI3RhYmxlKGlzLm5hKGRmX3B0X2lkJGNvbG91cikpCgojIyBtYWtlIGludG8gYSBkZgojZGZfcHRfaWQgPC0gZGZfcHRfaWRbICwiY29sb3VyIiwgZHJvcCA9IEZBTFNFXQoKIyMgYWRkIGJhY2sgdG8gc2V1cmF0IG9iamVjdApkZiA8LSBkZl9wdF9pZFsgLCJjb2xvdXIiLCBkcm9wID0gRkFMU0VdCnRlbnguanVzdHd0LmludGVncmF0ZWQgPC0gQWRkTWV0YURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGYsICJwdF9pZF9jb2xzIikKcm0oZGYpCgojIyBwbG90CiMjIGV4dHJhY3QgVU1BUCBjb29yZHMKZGZfdW1hcF9wbG90IDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAcmVkdWN0aW9uc1tbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzCmRmX3VtYXBfcGxvdCA8LSBtZXJnZShkZl91bWFwX3Bsb3QsIGRmX3B0X2lkLCBieT0wLCBhbGw9VFJVRSkKCiMjIGFkZCB0cmVlCiMjVGhlIHRyZWUgZm9yIG1vbm9jbGUgaXMgbG9jYXRlZCBoZXJlOgojIG1vbm9jbGUub2JqZWN0QHByaW5jaXBhbF9ncmFwaF9hdXhbWyJVTUFQIl1dJGRwX21zdCAKaWNhX3NwYWNlX2RmIDwtIHQobW9ub2NsZS5vYmplY3QuYWxsQHByaW5jaXBhbF9ncmFwaF9hdXhbWyJVTUFQIl1dJGRwX21zdCkgJT4lCiAgICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdF8ocHJpbl9ncmFwaF9kaW1fMSA9ICJVTUFQXzEiLCBwcmluX2dyYXBoX2RpbV8yID0gIlVNQVBfMiIpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKHNhbXBsZV9uYW1lID0gcm93bmFtZXMoLiksCiAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3N0YXRlID0gcm93bmFtZXMoLikpCgpkcF9tc3QgPC0gbW9ub2NsZS5vYmplY3QuYWxsQHByaW5jaXBhbF9ncmFwaFtbIlVNQVAiXV0KCmVkZ2VfZGYgPC0gZHBfbXN0ICU+JQogICAgICBpZ3JhcGg6OmFzX2RhdGFfZnJhbWUoKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdF8oc291cmNlID0gImZyb20iLCB0YXJnZXQgPSAidG8iKSAlPiUKICAgICAgZHBseXI6OmxlZnRfam9pbihpY2Ffc3BhY2VfZGYgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0XygKICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlPSJzYW1wbGVfbmFtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZV9wcmluX2dyYXBoX2RpbV8xPSJwcmluX2dyYXBoX2RpbV8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlX3ByaW5fZ3JhcGhfZGltXzI9InByaW5fZ3JhcGhfZGltXzIiKSwKICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJzb3VyY2UiKSAlPiUKICAgICAgZHBseXI6OmxlZnRfam9pbihpY2Ffc3BhY2VfZGYgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0XygKICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PSJzYW1wbGVfbmFtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldF9wcmluX2dyYXBoX2RpbV8xPSJwcmluX2dyYXBoX2RpbV8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0X3ByaW5fZ3JhcGhfZGltXzI9InByaW5fZ3JhcGhfZGltXzIiKSwKICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJ0YXJnZXQiKQoKIyMgbWFrZSBnZ3Bsb3QKdW1hcF9pZF9wdCA8LSBnZ3Bsb3QoZGZfdW1hcF9wbG90LCBhZXMoeCA9IFVNQVBfMSwgeSA9IFVNQVBfMikpICsgCiAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoY29sID0gZGZfdW1hcF9wbG90JGNvbG91cikgKwogICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKwogICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgZ2VvbV9zZWdtZW50KGFlc19zdHJpbmcoeD0ic291cmNlX3ByaW5fZ3JhcGhfZGltXzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT0ic291cmNlX3ByaW5fZ3JhcGhfZGltXzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeGVuZD0idGFyZ2V0X3ByaW5fZ3JhcGhfZGltXzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWVuZD0idGFyZ2V0X3ByaW5fZ3JhcGhfZGltXzIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWVkZ2VfZGYpCgp1bWFwX2lkX3B0CmBgYAoKc2F2ZQpgYGB7cn0KI2dnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC91bWFwX2lkX3B0LnBuZyIsIHBsb3QgPSB1bWFwX2lkX3B0LCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMSwgaGVpZ2h0ID0gMjkuNywgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYApjbHVzdGVyIHBsb3QKYGBge3J9CiMjIyBQcmVwYXJlIGRhdGEKCiMjIGV4dHJhY3QgZGYgd2l0aCBjbHVzdGVyIElELCAKZGZfcHRfaWQgPC0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbICwic2V1cmF0X2NsdXN0ZXJzIiwgZHJvcD1GQUxTRV0KIyMgZXh0cmFjdCBVTUFQIGNvb3JkcwpkZl9wbG90IDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAcmVkdWN0aW9uc1tbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzCmRmX3Bsb3QgPC0gbWVyZ2UoZGZfcGxvdCwgZGZfcHRfaWQsIGJ5PTAsIGFsbD1UUlVFKQojIyBhZGQgY29sb3VyIGNvbApkZl9wbG90JGNvbG91ciA8LSBkZl9wbG90JHNldXJhdF9jbHVzdGVycwpsZXZlbHMoZGZfcGxvdCRjb2xvdXIpIDwtIGxpc3QocHJpbnQoYXNleF9yYW1wKDE3KVsxXSkgPSAiOSIsIGFzZXhfcmFtcCgxNylbMl09IjQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbM109IjE1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs0XSA9ICI4IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs1XT0gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbNl09ICAiMTQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzddID0gIjIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzhdID0gIjEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzldID0gIjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTBdID0gIjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTFdID0gIjYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTJdID0gIjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTNdID0gIjciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTRdID0gIjEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzE1XSA9ICIxOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxNl0gPSAiMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTddID0gIjIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXBvdF9yYW1wKDMpWzJdID0gIjExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWxlX3JhbXAoMylbMl0gPSAiMTYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbGVfcmFtcCgzKVszXSA9ICIxMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVtYWxlX3JhbXAoNClbMl0gPSAiMjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlbWFsZV9yYW1wKDQpWzNdID0gIjIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZW1hbGVfcmFtcCg0KVs0XSA9ICIxOSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVtYWxlX3JhbXAoNClbNF0gPSAiMTciCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojIyBhYWJicmV2aWF0ZSBjbHVzdGVycwpkZl9wbG90JGNsdXN0ZXJfbmFtZXMgPC0gZGZfcGxvdCRzZXVyYXRfY2x1c3RlcnMKbGV2ZWxzKGRmX3Bsb3QkY2x1c3Rlcl9uYW1lcykgPC0gbGlzdChBXzE9IjkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzI9IjQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzM9IjE1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV80ID0gIjgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzUgPSAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV82PSAgIjE0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV83ID0gIjIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzggPSAiMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfOSA9ICIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzEwID0gIjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTEgPSAiNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMiA9ICI1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzEzID0gIjciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTQgPSAiMTIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTUgPSAiMTgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTYgPSAiMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTcgPSAiMjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEIgPSAiMTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1fMSA9ICIxNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTV8yID0gIjEzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzEgPSAiMjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMiA9ICIyMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8zID0gIjE5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzMgPSAiMTciCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKbGlicmFyeShkcGx5cikKZGF0JT4lCmdyb3VwX2J5KGN1c3RpZCklPiUgCnN1bW1hcmlzZShNZWFuPW1lYW4odmFsdWUpLCBNYXg9bWF4KHZhbHVlKSwgTWluPW1pbih2YWx1ZSksIE1lZGlhbj1tZWRpYW4odmFsdWUpLCBTdGQ9c2QodmFsdWUpKQoKCgojIyBwbG90CnVtYXBfaWQgPC0gZ2dwbG90KGRmX3Bsb3QsIGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yKSkgKyAKICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wb2ludChjb2wgPSBkZl9wbG90JGNvbG91cikgKwogICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKwogICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpCgp1bWFwX2lkCmBgYAoKYGBge3J9CiMjIHRoZXNlIGdldCBkZWZpbmVkIGxhdGVyIG9uLCBidXQgYXJlIHJlcGxpY2F0ZWQgYWJvdmUgaGVyZSBmb3IgcGxvdHRpbmcKYXNleHVhbF9lYXJseV9jbHVzdGVycyA8LSBjKDksIDQsIDE1LCA4LCAxLCAxNCwgMiwgMTAsIDMsIDAsIDYsIDUpCmFzZXh1YWxfbGF0ZV9jbHVzdGVycyA8LSBjKDcsIDEyLCAxOCwgMjAsIDIzKQpiaXBvdGVudGlvbmFsX2Vhcmx5X2NsdXN0ZXJzIDwtICMgMD8KYmlwb3RlbnRpYWxfY2x1c3RlcnMgPC0gYygxMSkgCm1hbGVfY2x1c3RlcnMgPC0gYygxNiwgMTMpCmZlbWFsZV9jbHVzdGVycyA8LSBjKDIxLCAyMiwgMTcsIDE5KQoKIyMgbWFrZSBhIG5ldyBjb2x1bW4gZm9yIHBsb3R0aW5nCnRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcgPC0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzCgojIyByZW9yZGVyIHRoZSBsZXZlbHMgc28geW91IGNhbiBwbG90IHRoZSBjbHV0ZXJzIGFzIHlvdSB3aXNoCm15X2xldmVscyA8LSBjKGFzZXh1YWxfZWFybHlfY2x1c3RlcnMsYXNleHVhbF9sYXRlX2NsdXN0ZXJzLCBiaXBvdGVudGlhbF9jbHVzdGVycywgbWFsZV9jbHVzdGVycywgZmVtYWxlX2NsdXN0ZXJzKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIDwtIGZhY3Rvcih4ID0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZywgbGV2ZWxzID0gbXlfbGV2ZWxzKQoKIyMgY2hhbmdlIHRoZSBsZXZlbHMKbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpIDwtIGxpc3QoQV8xPSI5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8yPSI0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8zPSIxNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNCA9ICI4IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV81ID0gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNj0gICIxNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNyA9ICIyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV84ID0gIjEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzkgPSAiMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMCA9ICIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzExID0gIjYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTIgPSAiNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMyA9ICI3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE0ID0gIjEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE1ID0gIjE4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE2ID0gIjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE3ID0gIjIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCID0gIjExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNXzEgPSAiMTYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1fMiA9ICIxMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8xID0gIjIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzIgPSAiMjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMyA9ICIxOSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8zID0gIjE3IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCiMjIyBBbm5vdGF0aW9uIHNldC11cAoKIyMgZXh0cmFjdCBwc2V1ZG90aW1lIG51bWJlcnMgYW5kIGlkZW50aXR5IG9mIGNlbGxzIHRvIGEgZGF0YWZyYW1lCmRmX3B0X2lkIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhWyxjKCJvbGRfcHRfdmFsdWVzIiwgIm1vbm9jbGVfc2V4IiwgInNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmciLCAiUHJlZGljdGlvbi5TcGVhcm1hbi4iLCAiUHJlZGljdGlvbi5TcGVhcm1hbi5fS2FzaWEiKV0KCiMjIG1ha2UgYSBuZXcgY29sdW1uCmRmX3B0X2lkJGNvbG91ciA8LSBOQQoKIyMgYXNzaWduIGJpbnMgdG8gZWFjaCBvZiB0aGUgdmFsdWVzCiMjIGhlbHAgaGVyZTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvOTk0NjYzMC9jb2xvdXItcG9pbnRzLWluLWEtcGxvdC1kaWZmZXJlbnRseS1kZXBlbmRpbmctb24tYS12ZWN0b3Itb2YtdmFsdWVzIApkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9FYXJseSIgfCBkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9MYXRlIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIk1hbGUiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiTWFsZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJGZW1hbGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKIyMgbWFrZSBjb2xvdXIgcmFtcHMKYXNleF9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0Q1RTNGNSIsICIjMDA1MmM1IikpCm1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIndoaXRlIiwgInllbGxvdyIsICIjMDE2YzAwIikpCmZlbWFsZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygieWVsbG93IiwgIiNhNTJiMWUiKSkKYmlwb3RfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIndoaXRlIiwgIiNmZmU0MDAiKSkKCiMjIGFzc2lnbiB2YWx1ZXMgdG8gZWFjaCBjbHVzdGVyCiMjIHRha2UgdGhlIG1lYW4gb2YgdGhlIGJpbgpkZl9hbm5vdGF0aW9uIDwtIGFnZ3JlZ2F0ZShkZl9wdF9pZFssICJjb2xvdXIiXSwgbGlzdChkZl9wdF9pZCRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSwgbWVhbikKIyMgQkVDQVVTRSB3ZSBoYXZlIG9yZGVyZWQgdGhlIGNsdXN0ZXJzIGFscmVhZHksIHdlIGNhbiBzaW1wbHkgdGFrZSB0aGUgcm93IGluZGV4IGZvciB0aGlzIGJpdApkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSBOQQpkZl9hbm5vdGF0aW9uWzE6MTcsIF0kY29sb3VyIDwtIGFzZXhfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMToxNywgXSR4XQpkZl9hbm5vdGF0aW9uWzE4LCBdJGNvbG91ciA8LSBiaXBvdF9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsxOCwgXSR4XQpkZl9hbm5vdGF0aW9uWzE5OjIwLCBdJGNvbG91ciA8LSBtYWxlX3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzE5OjIwLCBdJHhdCmRmX2Fubm90YXRpb25bMjE6MjMsIF0kY29sb3VyIDwtIGZlbWFsZV9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsyMToyMywgXSR4XQoKIyMgbWFrZSBjb2xvdXIgcGFsbGV0ZQojcGFsX3Bsb3QgPC0gYyhhc2V4X3JhbXAoMTcwKVsxLDExLDIxLDMxLF0sIGJpcG90X3JhbXAoMylbMl0sIG1hbGVfcmFtcCg1KVszOjRdLCBmZW1hbGVfcmFtcCg1KVsyOjVdKQpwYWxfcGxvdCA8LSBjKGRmX2Fubm90YXRpb24kY29sb3VyLCAnIzQ5QzE2REZGJykKCiMjIHBsb3QKdW1hcF93aXRoX2NsdXN0ZXJzIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwKICAgICAgICBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIiwKICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgIHB0LnNpemUgPSAxLAogICAgICAgIGxhYmVsLmJveCA9IFRSVUUsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDgsCiAgICAgICAgbGFiZWwuY29sb3IJPSBjKHJlcChjKCIjMDAwMDAwIiksIDEyKSwgcmVwKGMoIiNmZmZmZmYiKSwgNSksIHJlcChjKCIjMDAwMDAwIiksIDIpLCIjZmZmZmZmIiwgIiMwMDAwMDAiLCAiI2ZmZmZmZiIsICIjZmZmZmZmIiksCiAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICByZXBlbCA9IFRSVUUsIAogICAgICAgIGxhYmVsID0gVFJVRSwKICAgICAgICBjb2xzID0gcGFsX3Bsb3QpICsKICBzY2FsZV9jb2xvcl9tYW51YWwobGFiZWxzID0gYygiQXNleHVhbCAxIiwgIkFzZXh1YWwgMiIgLCAiQXNleHVhbCAzIiwgIkFzZXh1YWwgNCIsICJBc2V4dWFsIDUiLCAiQXNleHVhbCA2IiwgIkFzZXh1YWwgNyIsICJBc2V4dWFsIDgiLCAgIkFzZXh1YWwgOSIsICJBc2V4dWFsIDEwIiwgIkFzZXh1YWwgMTEiLCAiQXNleHVhbCAxMiIsICJBc2V4dWFsIDEzIiwgIkFzZXh1YWwgMTQiLCAiQXNleHVhbCAxNSIsICJBc2V4dWFsIDE2IiwgIkFzZXh1YWwgMTciLCAiQmlwb3RlbnRpYWwiLCAiTWFsZSAxIiwgIk1hbGUgMiIsICJGZW1hbGUgMSIsICJGZW1hbGUgMiIsICJGZW1hbGUgMyIpLCB2YWx1ZXMgPSBwYWxfcGxvdCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkKCnVtYXBfd2l0aF9jbHVzdGVycwpgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC91bWFwX3dpdGhfY2x1c3RlcnMucG5nIiwgcGxvdCA9IHVtYXBfd2l0aF9jbHVzdGVycywgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjUsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMjIyBkb3RwbG90CgpBIGRvdHBsb3QgYWxsb3dzIHVzIHRvIGxvb2sgYXQgdGhlIGV4cHJlc3Npb24gb2YgbXVsdGlwbGUgZ2VuZXMgaW4gYSBjbGVhcmVyIHdheSB0aGFuIHN1Y2Nlc2l2ZSBVTUFQIHBsb3RzCgpgYGB7ciwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodD0gOH0KIyMjIERhdGEgc2V0LXVwCgojIFBCQU5LQS0wODI4MDAwICAgICAgICAgR0NTS08tMyAgR0QxCgojIFBCQU5LQS0xMzAyNzAwICAgICAgIEdDU0tPLW9vbSAgTUQxIAojIFBCQU5LQS0xNDQ3OTAwICAgICAgICBHQ1NLTy0yOSAgTUQyCiMgUEJBTktBLTA0MTM0MDAgICAgR0NTS08tMTBfODIwICBNRDMKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENCAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1ENSAKCiMgUEJBTktBLTE0NTQ4MDAgICAgICAgIEdDU0tPLTIxICBGRDEKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0xNDE4MTAwICAgICAgICBHQ1NLTy0xNyAgRkQzICAgCiMgUEJBTktBLTE0MzUyMDAgICAgICAgIEdDU0tPLTIwICBGRDQgCgojIFBCQU5LQS0xNDM3NTAwIC0gQVAyRyAtIGNvbW1pdG1lbnQKIyBQQkFOS0EtMTMxOTUwMCAtIENDUDIgLSBmZW1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTA0MTYxMDAgLSBNRzEgLSBkeW5lbmluIGhlYXZ5IGNoYWluIC0gbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMDgzMTAwMCAtIE1TUDEgLSBsYXRlIGFzZXh1YWwKIyBQQkFOS0EtMTEwMjIwMCAtIE1TUDggLSBlYXJseSBhc2V4dWFsIChmcm9tIEJvemRlY2ggcGFwZXIpCgptYXJrZXJfZ2VuZXNfbGlzdCA8LSBjKCJQQkFOS0EtMTQzNzUwMCIsICJQQkFOS0EtMTMxOTUwMCIsICJQQkFOS0EtMDQxNjEwMCIsICJQQkFOS0EtMDgzMTAwMCIsICJQQkFOS0EtMTEwMjIwMCIpCm11dGFudF9nZW5lc19saXN0IDwtIGMoIlBCQU5LQS0wODI4MDAwIiwgIlBCQU5LQS0xMzAyNzAwIiwgIlBCQU5LQS0xNDQ3OTAwIiwgIlBCQU5LQS0wNDEzNDAwIiwgIlBCQU5LQS0wNzE2NTAwIiwgIlBCQU5LQS0wMTAyNDAwIiwgICJQQkFOS0EtMTQ1NDgwMCIsICJQQkFOS0EtMDkwMjMwMCIsICJQQkFOS0EtMTQxODEwMCIsICJQQkFOS0EtMTQzNTIwMCIpCgojIyB0aGVzZSBnZXQgZGVmaW5lZCBsYXRlciBvbiwgYnV0IGFyZSByZXBsaWNhdGVkIGFib3ZlIGhlcmUgZm9yIHBsb3R0aW5nCmFzZXh1YWxfZWFybHlfY2x1c3RlcnMgPC0gYyg5LCA0LCAxNSwgOCwgMSwgMTQsIDIsIDEwLCAzLCAwLCA2LCA1KQphc2V4dWFsX2xhdGVfY2x1c3RlcnMgPC0gYyg3LCAxMiwgMTgsIDIwLCAyMykKYmlwb3RlbnRpb25hbF9lYXJseV9jbHVzdGVycyA8LSAjIDA/CmJpcG90ZW50aWFsX2NsdXN0ZXJzIDwtIGMoMTEpIAptYWxlX2NsdXN0ZXJzIDwtIGMoMTYsIDEzKQpmZW1hbGVfY2x1c3RlcnMgPC0gYygyMSwgMjIsIDE3LCAxOSkKCiMjIGNvcHkgdGhlIGNsdXN0ZXJzIHNvIHlvdSBkb24ndCBwZXJtYW5lbnRseSBlZGl0IHRoZSBtYXN0ZXIKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnMKCiMjIHJlb3JkZXIgdGhlIGxldmVscyBzbyB5b3UgY2FuIHBsb3QgdGhlIGNsdXRlcnMgYXMgeW91IHdpc2gKbXlfbGV2ZWxzIDwtIGMoYXNleHVhbF9lYXJseV9jbHVzdGVycyxhc2V4dWFsX2xhdGVfY2x1c3RlcnMsIGJpcG90ZW50aWFsX2NsdXN0ZXJzLCBtYWxlX2NsdXN0ZXJzLCBmZW1hbGVfY2x1c3RlcnMpCgojIyByZW9yZGVyIHRoZSBsZXZlbHMKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyA8LSBmYWN0b3IoeCA9IHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcsIGxldmVscyA9IG15X2xldmVscykKCiMjIHJlbmFtZSBjbHVzdGVycyBzbyB0aGF0IHRoZXkgYXJlIGludHVpdGl2ZQojIHRoaXMgdHJpY2sgaXMgZnJvbSBoZXJlOiBodHRwOi8vd3d3LmNvb2tib29rLXIuY29tL01hbmlwdWxhdGluZ19kYXRhL1JlbmFtaW5nX2xldmVsc19vZl9hX2ZhY3Rvci8KbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpIDwtIGxpc3QoQXNleHVhbF8xPSI5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfMj0iNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzM9IjE1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfNCA9ICI4IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfNSA9ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF82PSAgIjE0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfNyA9ICIyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfOCA9ICIxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfOSA9ICIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xMCA9ICIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xMSA9ICI2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xMiA9ICI1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xMyA9ICI3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xNCA9ICIxMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfMTUgPSAiMTgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzE2ID0gIjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xNyA9ICIyMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJpcG90ZW50aWFsID0gIjExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFsZV8xID0gIjE2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFsZV8yID0gIjEzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmVtYWxlXzEgPSAiMjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGZW1hbGVfMiA9ICIyMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZlbWFsZV8zID0gIjE5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmVtYWxlXzMgPSAiMTciCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCiMjIyBBbm5vdGF0aW9uIHNldC11cAoKIyMgZXh0cmFjdCBwc2V1ZG90aW1lIG51bWJlcnMgYW5kIGlkZW50aXR5IG9mIGNlbGxzIHRvIGEgZGF0YWZyYW1lCmRmX3B0X2lkIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhWyxjKCJvbGRfcHRfdmFsdWVzIiwgIm1vbm9jbGVfc2V4IiwgInNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmciLCAiUHJlZGljdGlvbi5TcGVhcm1hbi4iLCAiUHJlZGljdGlvbi5TcGVhcm1hbi5fS2FzaWEiKV0KCiMjIG1ha2UgYSBuZXcgY29sdW1uCmRmX3B0X2lkJGNvbG91ciA8LSBOQQoKIyMgYXNzaWduIGJpbnMgdG8gZWFjaCBvZiB0aGUgdmFsdWVzCiMjIGhlbHAgaGVyZTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvOTk0NjYzMC9jb2xvdXItcG9pbnRzLWluLWEtcGxvdC1kaWZmZXJlbnRseS1kZXBlbmRpbmctb24tYS12ZWN0b3Itb2YtdmFsdWVzIApkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9FYXJseSIgfCBkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9MYXRlIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIk1hbGUiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiTWFsZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJGZW1hbGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKIyMgbWFrZSBjb2xvdXIgcmFtcHMKYXNleF9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0Q1RTNGNSIsICIjMDA1MmM1IikpCm1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIndoaXRlIiwgInllbGxvdyIsICIjMDE2YzAwIikpCmZlbWFsZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygieWVsbG93IiwgIiNhNTJiMWUiKSkKYmlwb3RfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIndoaXRlIiwgIiNmZmU0MDAiKSkKCiMjIGFzc2lnbiB2YWx1ZXMgdG8gZWFjaCBjbHVzdGVyCiMjIHRha2UgdGhlIG1lYW4gb2YgdGhlIGJpbgpkZl9hbm5vdGF0aW9uIDwtIGFnZ3JlZ2F0ZShkZl9wdF9pZFssICJjb2xvdXIiXSwgbGlzdChkZl9wdF9pZCRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSwgbWVhbikKIyMgQkVDQVVTRSB3ZSBoYXZlIG9yZGVyZWQgdGhlIGNsdXN0ZXJzIGFscmVhZHksIHdlIGNhbiBzaW1wbHkgdGFrZSB0aGUgcm93IGluZGV4IGZvciB0aGlzIGJpdApkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSBOQQpkZl9hbm5vdGF0aW9uWzE6MTcsIF0kY29sb3VyIDwtIGFzZXhfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMToxNywgXSR4XQpkZl9hbm5vdGF0aW9uWzE4LCBdJGNvbG91ciA8LSBiaXBvdF9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsxOCwgXSR4XQpkZl9hbm5vdGF0aW9uWzE5OjIwLCBdJGNvbG91ciA8LSBtYWxlX3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzE5OjIwLCBdJHhdCmRmX2Fubm90YXRpb25bMjE6MjMsIF0kY29sb3VyIDwtIGZlbWFsZV9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsyMToyMywgXSR4XQoKIyMgcGxvdCBhbm5vdGF0aW9uIAojIyB0aGlzIHJlYWxseSBoZWxwZWQ6IGh0dHBzOi8vd3d3LmJpb3N0YXJzLm9yZy9wLzM5NjgxMC8KaDIgPC0gZ2dwbG90KGRmX2Fubm90YXRpb24pKwogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIHkgPSAxKSwgCiAgICAgICAgICAgc3RhdCA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgZmlsbCA9IGRmX2Fubm90YXRpb24kY29sb3VyLAogICAgICAgICAgIGNvbCA9ICIjRkZGRkZGIiwKICAgICAgICAgICB3aWR0aCA9IDEpKwogICAgICB0aGVtZV92b2lkKCkrCiAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpIysKICAgICAjZmFjZXRfZ3JpZCgufmNvbG91ciwgc2NhbGVzID0gImZyZWVfeCIpCiAgICAgI2xlZ2VuZCA8LSBwbG90X2dyaWQoZ2V0X2xlZ2VuZChoMiksIGdldF9sZWdlbmQoaDEpLCBuY29sID0gMSkKIGgyIDwtIGgyICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQogIyAgIGdlb21fcG9pbnQoY29sID0gZGZfdW1hcF9wbG90JGNvbG91cikKIAogaDEgPC0gZ2dwbG90KGRmX2Fubm90YXRpb24pKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gR3JvdXAuMSwgeSA9IDEpLAogICAgICAgICAgICBjb2wgPSBkZl9hbm5vdGF0aW9uJGNvbG91ciwKICAgICAgICAgICAgc2l6ZSA9IDUpKwogICAgICB0aGVtZV92b2lkKCkrCiAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpIysKICAgICAjZmFjZXRfZ3JpZCgufmNvbG91ciwgc2NhbGVzID0gImZyZWVfeCIpCiAgICAgI2xlZ2VuZCA8LSBwbG90X2dyaWQoZ2V0X2xlZ2VuZChoMiksIGdldF9sZWdlbmQoaDEpLCBuY29sID0gMSkKIGgxIDwtIGgxICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQogIyAgIGdlb21fcG9pbnQoY29sID0gZGZfdW1hcF9wbG90JGNvbG91cikKCiAjIyBhZGQgcHJlZGljdGVkIHRpbWUgcG9pbnQKICMjIHRha2UgdGhlIG1lYW4gb2YgdGhlIGJpbgpkZl9hbm5vdGF0aW9uIDwtIGFnZ3JlZ2F0ZShkZl9wdF9pZFssICJQcmVkaWN0aW9uLlNwZWFybWFuLiJdLCBsaXN0KGRmX3B0X2lkJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpLCBtZWFuKQpkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSBOQQpkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSB2aXJpZGlzKDMwMClbKGRmX2Fubm90YXRpb24keCkqMTBdCgpoMyA8LSBnZ3Bsb3QoZGZfYW5ub3RhdGlvbikrCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gR3JvdXAuMSwgeSA9IDEpLCAKICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBmaWxsID0gZGZfYW5ub3RhdGlvbiRjb2xvdXIsCiAgICAgICAgICAgY29sID0gIiNGRkZGRkYiLAogICAgICAgICAgIHdpZHRoID0gMSkrCiAgICAgIHRoZW1lX3ZvaWQoKSsKICAgICAgdGhlbWUocGFuZWwuc3BhY2luZy54ID0gdW5pdCgxLCAibW0iKSkjKwogICAgICNmYWNldF9ncmlkKC5+Y29sb3VyLCBzY2FsZXMgPSAiZnJlZV94IikKICAgICBsZWdlbmRfaDMgPC0gZ2V0X2xlZ2VuZChoMykKIGgzIDwtIGgzICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKICBoMyA8LSBnZ3Bsb3QoZGF0YSA9IGRmX2Fubm90YXRpb24sIAogICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIGZpbGw9eCkKICAgICAgICAgICAgICApICsKICAgICAgIGdlb21fYmFyKGNvbCA9ICIjRkZGRkZGIiwgd2lkdGggPSAxKSsKICAgICAgIHRoZW1lX3ZvaWQoKSArCiAgICAgICB0aGVtZShwYW5lbC5zcGFjaW5nLnggPSB1bml0KDEsICJtbSIpKSArCiAgICAgICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uID0gJ2NpdmlkaXMnKQogbGVnZW5kX2gzIDwtIGdldF9sZWdlbmQoaDMpCiBoMyA8LSBoMyArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKIAogIyMgYWRkIGthc2lhIGRhdGEKICAjIyB0YWtlIHRoZSBtZWFuIG9mIHRoZSBiaW4KZGZfYW5ub3RhdGlvbiA8LSBhZ2dyZWdhdGUoZGZfcHRfaWRbLCAiUHJlZGljdGlvbi5TcGVhcm1hbi5fS2FzaWEiXSwgbGlzdChkZl9wdF9pZCRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSwgbWVhbikKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gTkEKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gdmlyaWRpcygzMDApWyhkZl9hbm5vdGF0aW9uJHgpKjEwXQoKaDQgPC0gZ2dwbG90KGRmX2Fubm90YXRpb24pKwogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIHkgPSAxKSwgCiAgICAgICAgICAgc3RhdCA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgZmlsbCA9IGRmX2Fubm90YXRpb24kY29sb3VyLAogICAgICAgICAgIGNvbCA9ICIjRkZGRkZGIiwKICAgICAgICAgICB3aWR0aCA9IDEpKwogICAgICB0aGVtZV92b2lkKCkrCiAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpKwogICAgIGZhY2V0X2dyaWQoLn5jb2xvdXIsIHNjYWxlcyA9ICJmcmVlX3giKQogICAgIGxlZ2VuZCA8LSBwbG90X2dyaWQoZ2V0X2xlZ2VuZChoNCksIG5jb2wgPSAxKQogICAgbGVnZW5kX2g0IDwtIGdldF9sZWdlbmQoaDQpCiBoNCA8LSBoNCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiBoNCA8LSBnZ3Bsb3QoZGF0YSA9IGRmX2Fubm90YXRpb24sIAogICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIGZpbGw9eCkKICAgICAgICAgICAgICApICsKICAgICAgIGdlb21fYmFyKGNvbCA9ICIjRkZGRkZGIiwgd2lkdGggPSAxKSsKICAgICAgIHRoZW1lX3ZvaWQoKSArCiAgICAgICB0aGVtZShwYW5lbC5zcGFjaW5nLnggPSB1bml0KDEsICJtbSIpKSArCiAgICAgICBzY2FsZV9maWxsX3ZpcmlkaXMoKQogbGVnZW5kX2g0IDwtIGdldF9sZWdlbmQoaDQpCiBoNCA8LSBoNCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiMjIyBQbG90CmRvdF9wbG90X21hcmtlcnMgPC0gRG90UGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gYyhtYXJrZXJfZ2VuZXNfbGlzdCwgcmV2KG11dGFudF9nZW5lc19saXN0KSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG90Lm1pbiA9IDAuMDAwMDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheSA9ICdSTkEnKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBjb29yZF9maXhlZCgpICsKICBjb29yZF9mbGlwKCkgKwogICMgY2hhbmdlIGFwcGVhcmFuY2UgYW5kIHJlbW92ZSBheGlzIGVsZW1lbnRzLCBhbmQgbWFrZSByb29tIGZvciBhcnJvd3MKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBhbmdsZSA9IDQ1LCBoanVzdD0xLHZqdXN0PTEsIGZhbWlseSA9ICJBcmlhbCIpLCAKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBmYWNlPSJpdGFsaWMiKSwgCiAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNiwgZmFtaWx5PSJBcmlhbCIsIGNvbG91cj0iYmxhY2siKSwgCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIAogICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsIAogICAgICAgIGxlZ2VuZC5ib3ggPSAidmVydGljYWwiLCAKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLDMsMSwzKSwgImxpbmVzIiksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbD1OQSwgc2l6ZT0wLjUpKSArCiAgI2NoYW5nZSB0aGUgY29sb3VycwogICNzY2FsZV9jb2xvdXJfdmlyaWRpcyhvcHRpb24gPSAiaW5mZXJubyIsIGd1aWRlID0gImNvbG91cmJhciIsIG5hLnZhbHVlPSJ3aGl0ZSIsIGJlZ2luID0gMCwgZW5kID0gMSwgZGlyZWN0aW9uID0gMSkgKwogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBjaGFuZ2UgeCBheGlzIGxhYmVsCiAgIyBsYWJzKHggPSAiTWFya2VyIEdlbmVzIiwgeSA9ICJDbHVzdGVyIiwgdGl0bGUgPSAiRXhwcmVzc2lvbiBvZiBNYXJrZXIgR2VuZXMgYnkgQ2x1c3RlciIpIAogIGxhYnMoeCA9ICIiLCB5ID0gIiIsIHRpdGxlID0gIiIpICsKICAjIyBhZGQgYXJyb3dzCiAgI2Fubm90YXRlKCJzZWdtZW50IiwgeCA9IDUuNSwgeGVuZCA9IDUuNSwgeSA9IDIxLjUsIHllbmQgPSAyNSwgY29sb3VyID0gImdyZWVuIiwgc2l6ZT0xLCBhbHBoYT0xLCBhcnJvdz1hcnJvdyhsZW5ndGg9dW5pdCgwLjMwLCJjbSIpLCB0eXBlID0gImNsb3NlZCIpKSArCiAgI2Fubm90YXRlKCJzZWdtZW50IiwgeCA9IDUuNSwgeGVuZCA9IDUuNSwgeSA9IDE2LjUsIHllbmQgPSAyMS41LCBjb2xvdXIgPSAicmVkIiwgc2l6ZT0xLCBhbHBoYT0xLCBhcnJvdz1hcnJvdyhsZW5ndGg9dW5pdCgwLjMwLCJjbSIpLCB0eXBlID0gImNsb3NlZCIpKSArCiAgI2Fubm90YXRlKCJzZWdtZW50IiwgeCA9IDUuNSwgeGVuZCA9IDUuNSwgeSA9IDAsIHllbmQgPSAxNS41LCBjb2xvdXIgPSAiZ3JleSIsIHNpemU9MSwgYWxwaGE9MSwgYXJyb3c9YXJyb3cobGVuZ3RoPXVuaXQoMC4zMCwiY20iKSwgdHlwZSA9ICJjbG9zZWQiKSkgKwogICMjIGFubm90YXRlIGFzZXgKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gKGxlbmd0aChjKGFzZXh1YWxfZWFybHlfY2x1c3RlcnMsIGFzZXh1YWxfbGF0ZV9jbHVzdGVycykpKzAuNSkpLCBzaXplID0gMC41LCBsaW5ldHlwZT0gJ2Rhc2hlZCcpICsKICAjIyBhbm5vdGF0ZSBiaXBvdGVudGlhbAogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAobGVuZ3RoKGMoYXNleHVhbF9lYXJseV9jbHVzdGVycywgYXNleHVhbF9sYXRlX2NsdXN0ZXJzLCBiaXBvdGVudGlhbF9jbHVzdGVycykpKzAuNSkpLCBzaXplID0gMC41LCBsaW5ldHlwZT0gJ2Rhc2hlZCcpICsKICAjIyBhbm5vdGF0ZSBzZXhlcwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAobGVuZ3RoKGMoYXNleHVhbF9lYXJseV9jbHVzdGVycywgYXNleHVhbF9sYXRlX2NsdXN0ZXJzLCBiaXBvdGVudGlhbF9jbHVzdGVycywgbWFsZV9jbHVzdGVycykpKzAuNSkpLCBzaXplID0gMC41LCBsaW5ldHlwZT0gJ2Rhc2hlZCcpICsKICAjIyBjaGFuZ2UgbGFiZWwgb24gYm90dG9tIG9mIHBsb3Qgc28gd2UgY2FuIGluZGljYXRlIG1hcmtlcnMKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IHJldihjKCJnZDEiLCAibWQxIiwgIm1kMiIsICJtZDMiLCAibWQ0IiwgIm1kNSIsICJmZDEiLCAiZmQyIiwgImZkMyIsICJmZDQiLCAibXNwOCIsICJtc3AxIiwgIm1nMSIsICJjY3AyIiwgImFwMmciKSkpICsKICAjIyBjaGFuZ2UgbGFiZWwgb24gYm90dG9tIG9mIHBsb3Qgc28gd2UgY2FuIGluZGljYXRlIG1hcmtlcnMKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIkFzZXh1YWwgMSIsICJBc2V4dWFsIDIiICwgIkFzZXh1YWwgMyIsICJBc2V4dWFsIDQiLCAiQXNleHVhbCA1IiwgIkFzZXh1YWwgNiIsICJBc2V4dWFsIDciLCAiQXNleHVhbCA4IiwgICJBc2V4dWFsIDkiLCAiQXNleHVhbCAxMCIsICJBc2V4dWFsIDExIiwgIkFzZXh1YWwgMTIiLCAiQXNleHVhbCAxMyIsICJBc2V4dWFsIDE0IiwgIkFzZXh1YWwgMTUiLCAiQXNleHVhbCAxNiIsICJBc2V4dWFsIDE3IiwgIkJpcG90ZW50aWFsIiwgIk1hbGUgMSIsICJNYWxlIDIiLCAiRmVtYWxlIDEiLCAiRmVtYWxlIDIiLCAiRmVtYWxlIDMiKSkgKwogICMjIGNoYW5nZSBuYW1lIG9mIGxlZ2VuZHMKICBndWlkZXMoY29sPWd1aWRlX2NvbG9yYmFyKHRpdGxlID0gJ1NjYWxlZCBBdmVyYWdlIEV4cHJlc3Npb24nKSwKICAgICAgICAgc2l6ZT1ndWlkZV9sZWdlbmQoIiUgb2YgY2VsbHMgZXhwcmVzc2luZyIpKQoKIyMgdmlldwojcHJpbnQoZG90X3Bsb3RfbWFya2VycykKCnBsb3QgPC0gcGxvdF9ncmlkKGg0LCBoMywgaDEsIGRvdF9wbG90X21hcmtlcnMsIGFsaWduID0gInYiLCBuY29sID0gMSwgYXhpcyA9ICJ0YiIsIHJlbF9oZWlnaHRzID0gYygwLjUsIDAuNSwgMC41LCAxOCkpIAoKZG90X3Bsb3QgPC0gcGxvdF9ncmlkKHBsb3QsIGxlZ2VuZF9oMywgbGVnZW5kX2g0LCBucm93ID0gMSwgcmVsX3dpZHRocyA9IGMoMTAsIDEuNSwgMS41KSkKCmRvdF9wbG90CmBgYAoKc2F2ZQpgYGB7cn0KZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L2RvdF9wbG90X2FsbC5wbmciLCBwbG90ID0gZG90X3Bsb3QsIGRldmljZSA9ICJwbmciLCBwYXRoID0gTlVMTCwgc2NhbGUgPSAxLCB3aWR0aCA9IDI5LjcsIGhlaWdodCA9IDIxLCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCgojIDkuIFN1YnNldCBzZXh1YWwgY2VsbHMgey50YWJzZXR9CgpNYWtlIGEgc3Vic2V0dGVkIFNldXJhdCBvYmplY3Qgb2Ygc2V4dWFsIGNlbGxzLiAKCkluY2x1ZGUgdGhlIHByZS1icmFuY2ggdG9vIGFzIHdlbGwgYXMgYW55IHdlaXJkIGNsdXN0ZXJzIHRoYXQgbWF5IGhhdmUgY2x1c3RlcmVkIG91dC4gCgppdCdzIGJlZW4gYSB3aGlsZSBzaW5jZSB3ZSBsb29rZWQgYXQgdGhlIGNsdXN0ZXJzIHNvIGxldCdzIGNoZWNrIHRoZW0gb3V0IGFnYWluOgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyMgUGxvdApEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBGQUxTRSwgcHQuc2l6ZSA9IDAuMDUsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIikgKyBjb29yZF9maXhlZCgpCgojIyBwbG90Cmxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzNdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s1XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzZdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbN11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s4XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzldXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTBdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTFdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTJdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTNdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTRdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTVdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTZdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTddXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMThdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTldXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMjBdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMjFdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMjJdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMjNdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMjRdXQpgYGAKCiMjIyBEZWZpbmUgY2VsbHMgYW5kIHN1YnNldApgYGB7cn0KYXNleHVhbF9lYXJseV9jbHVzdGVycyA8LSBjKDksIDQsIDE1LCA4LCAxLCAxNCwgMiwgMTAsIDMsIDAsIDYsIDUpCmFzZXh1YWxfbGF0ZV9jbHVzdGVycyA8LSBjKDcsIDEyLCAxOCwgMjAsIDIzKQpiaXBvdGVudGlvbmFsX2Vhcmx5X2NsdXN0ZXJzIDwtICMgMD8KYmlwb3RlbnRpYWxfY2x1c3RlcnMgPC0gYygxMSkgCm1hbGVfY2x1c3RlcnMgPC0gYygxNiwgMTMpCmZlbWFsZV9jbHVzdGVycyA8LSBjKDIxLCAyMiwgMTcsIDE5KQoKIyMgZGVmaW5lIGNlbGxzCmNlbGxfbmFtZXNfc3Vic2V0X21vbm9jbGVfaWRzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhW3RlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJG1vbm9jbGVfc2V4ICVpbiUgYygiQXNleHVhbF9FYXJseSIsICJCaXBvdGVudGlhbCIsICJNYWxlIiwgIkZlbWFsZSIpLCBdKQoKIyMgMywgMCwgNiwgNSBhcmUgZWFybHkgY2x1c3RlcnMgb2YgYXNleHVhbHMgYmVmb3JlIHRoZSBicmFuY2gKY2VsbF9uYW1lc19zdWJzZXRfY2x1c3Rlcl9pZHMgPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzICVpbiUgYyhtYWxlX2NsdXN0ZXJzLCBmZW1hbGVfY2x1c3RlcnMsIGJpcG90ZW50aWFsX2NsdXN0ZXJzLCAzLCAwLCA2LCA1KSwgXSkKCmNlbGxfbmFtZXNfc3Vic2V0X2ludGVyc2VjdCA8LSBpbnRlcnNlY3QoY2VsbF9uYW1lc19zdWJzZXRfbW9ub2NsZV9pZHMsIGNlbGxfbmFtZXNfc3Vic2V0X2NsdXN0ZXJfaWRzKQoKIyMgc3Vic2V0IGNlbGxzIGludG8gbmV3IG9iamVjdAp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCA8LSBzdWJzZXQodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgY2VsbHMgPSBjZWxsX25hbWVzX3N1YnNldF9pbnRlcnNlY3QpCmBgYAoKIyMjIGluc3BlY3QvY2hlY2sKYGBge3J9CiMjIGluc3BlY3Qgb2JqZWN0CnRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4CgojIyBsb29rIGF0IG9yaWdpbmFsIFVNQVAKRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjEsIHNwbGl0LmJ5ID0gImV4cGVyaW1lbnQiLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIpICsgY29vcmRfZml4ZWQoKQpgYGAKCiMjIyBSZW1vdmUgY29udGFtaW5hbnQgYXNleHVhbCBjZWxscwoKd2Ugd2FudCB0byByZW1vdmU6CmBgYHtyfQojIyBsb29rIGF0IG9yaWdpbmFsIFVNQVAKcGxvdF9zZXh1YWxfc3Vic2V0dGluZyA8LSBEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LCBsYWJlbCA9IFRSVUUsIHJlcGVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuMSwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiKSArIAogIGNvb3JkX2ZpeGVkKCkgKyAKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gLTEsIGFscGhhID0gNSkpCgpwbG90X3NleHVhbF9zdWJzZXR0aW5nCmBgYAoKYGBge3J9CiMjIGV4dHJhY3QgY2VsbCBlbWJlZGRpbmdzCmRmX3NleF9jZWxsX2VtYmVkZGluZ3MgPC0gYXMuZGF0YS5mcmFtZSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MpCgojIyBzdWJzZXQgYW55dGhpbmcgbG93ZXIgdGhhbiAtMC44IGluIFVNQVAgMiBhbmQgLTAuMSBpbiBVTUFQIDEKcmVtb3ZlX2NlbGxzIDwtIHJvdy5uYW1lcyhkZl9zZXhfY2VsbF9lbWJlZGRpbmdzW3doaWNoKGRmX3NleF9jZWxsX2VtYmVkZGluZ3MkVU1BUF8xIDwgLTEpLCBdKQoKIyMgcGxvdCB0aGVzZSBjZWxscwpEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LCBsYWJlbCA9IEZBTFNFLCByZXBlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjEsIGNlbGxzLmhpZ2hsaWdodCA9IHJlbW92ZV9jZWxscywgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiKSArIAogIGNvb3JkX2ZpeGVkKCkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiI2Y1NGUxZSIpKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiY2VsbHMgaGlnaGxpZ2h0ZWQgd2lsbCBiZSByZW1vdmVkIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgojIyBGaW5hbCBTdWJzZXQKYGBge3J9CiMjIG1ha2Uga2VlcCBjZWxscyBmcm9tIHRoZSByZW1vdmVfY2VsbHMKIyMgbWFrZSB0aGUgbm90IGluIGZ1bmN0aW9uCiclbmklJyA8LSBOZWdhdGUoJyVpbiUnKQprZWVwX2NlbGxzIDwtIGNvbG5hbWVzKHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4KVt3aGljaChjb2xuYW1lcyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCkgJW5pJSByZW1vdmVfY2VsbHMpXQoKIyMgc3Vic2V0CnRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4IDwtIHN1YnNldCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgY2VsbHMgPSBrZWVwX2NlbGxzKQoKIyMgaW5zcGVjdAp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleApgYGAKCmNvcHkgb2xkIGNsdXN0ZXJzIG92ZXIKYGBge3J9CiMjIGNvcHkgb2xkIGNsdXN0ZXJzCnRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4IDwtIEFkZE1ldGFEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LCB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzLCBjb2wubmFtZSA9ICJwb3N0X2ludGVncmF0aW9uX2NsdXN0ZXJzIikKYGBgCgojIDEwLiBTZXggYXNzaWdubWVudCBvZiBtdXRhbnRzIAoKIyMgQS4gU2V1cmF0IE1ldGhvZAoKYGBge3J9CiMjIGZpbmQgdHJhbnNmZXIgYW5jaG9ycwpEZWZhdWx0QXNzYXkodGVueC5qdXN0d3QuaW50ZWdyYXRlZCkgPC0gImludGVncmF0ZWQiCm1lcmdlLmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycyhyZWZlcmVuY2UgPSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBxdWVyeSA9IEdDU0tPX211dGFudHMsIAogICAgZGltcyA9IDE6MzApCgojIyB0cmFuc2ZlciBkYXRhIGJldHdlZW4gcmVmIGFuZCBxdWVyeQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gbWVyZ2UuYW5jaG9ycywgcmVmZGF0YSA9IHRlbnguanVzdHd0LmludGVncmF0ZWQkbW9ub2NsZV9zZXgsIAogICAgZGltcyA9IDE6MzApCgojIyBhZGQgbWV0YSBkYXRhIHRvIG9iamVjdApHQ1NLT19tdXRhbnRzIDwtIEFkZE1ldGFEYXRhKEdDU0tPX211dGFudHMsIG1ldGFkYXRhID0gcHJlZGljdGlvbnMpCgojIyBuZXcgb2JqZWN0IGZyb20gdGhpcwptdXRhbnRfc2V1cmF0IDwtIEdDU0tPX211dGFudHMKCiMjIGxvb2sgYXQgYnJlYWtkb3duIG9mIG11dGFudCBieSBkZXNpZ25hdGlvbgpkZiA8LSBhcy5kYXRhLmZyYW1lKG11dGFudF9zZXVyYXRAbWV0YS5kYXRhKQp0YWJsZShkZiRwcmVkaWN0ZWQuaWQsIGRmJGlkZW50aXR5X25hbWVfdXBkYXRlZCkKYGBgCgpgYGB7cn0KIyMgc2VlIGhvdyB0aGlzIG92ZXJsYXBzIHdpdGggZmx1b3Jlc2NlbmNlIHNvcnRlZCBvbiBmb3IgODIwIHRvIGNvbmZpcm0gYWNjdXJhY3kKZGZfODIwIDwtIGRmW2RmJGdlbmV0aWNfYmFja2dyb3VuZCA9PSJQQkFOS0FfODIwIiwgXQp0YWJsZShkZl84MjAkcHJlZGljdGVkLmlkLCBkZl84MjAkZmx1b3Jlc2VuY2Vfc29ydGVkX29uKQpgYGAKCgpDYWxjdWxhdGUgc2V4IHJhdGlvcwpgYGB7cn0KIyMgdXNlIGRlc2lnbmF0aW9ucyBhYm92ZSBmb3Igc2V4ZXMKbWFsZV9jZWxscyA8LSByb3duYW1lcyhtdXRhbnRfc2V1cmF0QG1ldGEuZGF0YVttdXRhbnRfc2V1cmF0QG1ldGEuZGF0YSRwcmVkaWN0ZWQuaWQgPT0gIk1hbGUiLCBdKQpmZW1hbGVfY2VsbHMgPC0gcm93bmFtZXMobXV0YW50X3NldXJhdEBtZXRhLmRhdGFbbXV0YW50X3NldXJhdEBtZXRhLmRhdGEkcHJlZGljdGVkLmlkID09ICJGZW1hbGUiLCBdKQpzczJfbXV0YW50c19maW5hbF9tYWxlIDwtIHN1YnNldChtdXRhbnRfc2V1cmF0LCBjZWxscyA9IG1hbGVfY2VsbHMpCnNzMl9tdXRhbnRzX2ZpbmFsX2ZlbWFsZSA8LSBzdWJzZXQobXV0YW50X3NldXJhdCwgY2VsbHMgPSBmZW1hbGVfY2VsbHMpCgojIyBpbnNwZWN0CnNzMl9tdXRhbnRzX2ZpbmFsX21hbGUKc3MyX211dGFudHNfZmluYWxfZmVtYWxlCmBgYAoKYGBge3J9CiMjIGNhbGN1bGF0ZSBzZXggcmF0aW9zCiMjc3Vic2V0IG91dCBILCBzb3J0ZWQgY2VsbHM6CmRmX21hbGUgPC0gc3MyX211dGFudHNfZmluYWxfbWFsZUBtZXRhLmRhdGFbc3MyX211dGFudHNfZmluYWxfbWFsZUBtZXRhLmRhdGEkZXhjbHVkZV9mb3Jfc2V4X3JhdGlvID09IEZBTFNFLF0KCmRpbShkZl9tYWxlKQoKZGZfZmVtYWxlIDwtIHNzMl9tdXRhbnRzX2ZpbmFsX2ZlbWFsZUBtZXRhLmRhdGFbc3MyX211dGFudHNfZmluYWxfZmVtYWxlQG1ldGEuZGF0YSRleGNsdWRlX2Zvcl9zZXhfcmF0aW8gPT0gRkFMU0UsXQoKZGltKGRmX2ZlbWFsZSkKCiMjIG1ha2UgZGF0YWZyYW1lCmRmX3NleF9yYXRpbyA8LSBtZXJnZSgKICBhcy5kYXRhLmZyYW1lKHRhYmxlKGRmX21hbGUkc3ViX25hbWVfdXBkYXRlZCkpLCAKICBhcy5kYXRhLmZyYW1lKHRhYmxlKGRmX2ZlbWFsZSRzdWJfbmFtZV91cGRhdGVkKSksIAogIGJ5ID0gIlZhcjEiLCBhbGw9VFJVRSkKCiMgb3IgdXNlIGlkZW50aXR5X3VwZGF0ZWQKCiMjIGFkZCBuYW1lcwpuYW1lcyhkZl9zZXhfcmF0aW8pIDwtIGMoImdlbm90eXBlIiwgIm1hbGUiLCAiZmVtYWxlIikKCiMjIGNoYW5nZSB0aGUgTkFzIHRvIDAKZGZfc2V4X3JhdGlvW2lzLm5hKGRmX3NleF9yYXRpbyldIDwtIDAKCiMjIGNvbGxhcHNlIDgyMCB3aWxkLXR5cGVzIHRvZ2V0aGVyCmNvbWJpbmVkX20gPC0gZGZfc2V4X3JhdGlvW2RmX3NleF9yYXRpbyRnZW5vdHlwZSA9PSAiV1QtODIwXzNfNSIsIF0kbWFsZSArIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMCIsIF0kbWFsZQpjb21iaW5lZF9mIDwtIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMF8zXzUiLCBdJGZlbWFsZSArIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMCIsIF0kZmVtYWxlCmRmX3NleF9yYXRpbyA8LSByYmluZChkZl9zZXhfcmF0aW8sIGMoIldULTgyMC1jb21iaW5lZCIsIGNvbWJpbmVkX20sIGNvbWJpbmVkX2YpKQojIHJlbW92ZSBvbGQgcm93cwpkZl9zZXhfcmF0aW8gPC0gZGZfc2V4X3JhdGlvWy13aGljaChkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMF8zXzUiIHwgZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC04MjAiKSwgXQojIG5lZWQgdG8gbWFrZSBudW1lcmljIGFnYWluCmRmX3NleF9yYXRpbyRtYWxlIDwtIGFzLm51bWVyaWMoZGZfc2V4X3JhdGlvJG1hbGUpCmRmX3NleF9yYXRpbyRmZW1hbGUgPC0gYXMubnVtZXJpYyhkZl9zZXhfcmF0aW8kZmVtYWxlKQpkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPC0gYXMuY2hhcmFjdGVyKGRmX3NleF9yYXRpbyRnZW5vdHlwZSkKIyBhZGQgbmFtZSBmb3IgV1QgY29tYmluZWQKZGZfc2V4X3JhdGlvJGdlbm90eXBlWzE3XSA8LSAiV1QtODIwLWNvbWJpbmVkIgoKIyMgY2FsY3VsYXRlIHNleCByYXRpbwpkZl9zZXhfcmF0aW8kc2V4X3JhdGlvIDwtIChkZl9zZXhfcmF0aW8kbWFsZSArIDAuMSkvKGRmX3NleF9yYXRpbyRmZW1hbGUgKyAwLjEpCgojIyBsb2cgc2V4IHJhdGlvCmRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nIDwtIGxvZzEwKGRmX3NleF9yYXRpbyRzZXhfcmF0aW8pCgojI3ZpZXcKZGZfc2V4X3JhdGlvCmBgYAoKYGBge3J9CiMjIHJlbW92ZSBXVC0yIGJlY2F1c2UgaXQgaXMgcmVhbGx5IGluYXBwcm9wcmlhdGUgdG8gaGF2ZSBhIHNleCByYXRpbyBmb3IgdGhpczoKZGZfc2V4X3JhdGlvIDwtIGRmX3NleF9yYXRpb1std2hpY2goZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC1tZDUiKSxdCmBgYAoKcGxvdApgYGB7ciwgZmlnLmhlaWdodCA9IDcsIGZpZy53aWR0aCA9IDZ9CmxpYnJhcnkobGF0ZXgyZXhwKSAjIHNvIHlvdSBjYW4gcGxvdCB0aGUgZnJhY3Rpb24sIGl0J3Mgb24gQ1JBTiBgaW5zdGFsbC5wYWNrYWdlcygibGF0ZXgyZXhwIilgCgojIyBtYWtlIGV4dHJhIGNvbHVtbiBmb3IgcGxvdHRpbmcgYWVzdGhldGljczoKZGZfc2V4X3JhdGlvJGFib3ZlIDwtIGRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nID4gMAoKIyMgbWFrZSBleHRyYSBjb2x1bW4gd2l0aCByYXRpbyBpbiBpdDoKZGZfc2V4X3JhdGlvJGdlbm90eXBlX3dpdGhfbiA8LSBwYXN0ZTAoZGZfc2V4X3JhdGlvJGdlbm90eXBlLCAiICgiLCBkZl9zZXhfcmF0aW8kbWFsZSwgIi8iLCBkZl9zZXhfcmF0aW8kZmVtYWxlLCAiKSIpCgojIyByZW9yZGVyIGdlbm90eXBlIHNvIGl0IGlzIGluIHRoZSBjb3JyZWN0IG9yZGVyIGZvciBwbG90dGluZwpkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uIDwtIGZhY3RvcihkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uLCBsZXZlbHMgPSBkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uW29yZGVyKGRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nKV0pCgojIyBwbG90CnNleF9yYXRpb19wbG90IDwtIGdncGxvdChkZl9zZXhfcmF0aW8sIGFlcyhzZXhfcmF0aW9fbG9nLCBnZW5vdHlwZV93aXRoX24sIGNvbG9yID0gYWJvdmUpKSArCiAgICAgICMjIGFkZCB0aGUgbGluZXMgZm9yIHRoZSBsb2xsaXBvcCBwbG90CiAgICAgIGdlb21fc2VnbWVudChhZXMoeCA9IDAsIHkgPSBnZW5vdHlwZV93aXRoX24sIHhlbmQgPSBzZXhfcmF0aW9fbG9nLCB5ZW5kID0gZ2Vub3R5cGVfd2l0aF9uKSwgY29sb3IgPSAiZ3JleTUwIikgKwogICAgICAjIyBhZGQgdGhlIHBvaW50cyBmb3IgdGhlIGxvbGxpcG9wIHBsb3QKICAgICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IDQpKSArCiAgICAgICMjIGFkZCB0aGUgd2lsZC10eXBlIHJlY3RhbmdsZQogICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49IC0wLjIzMTgyNDc4LCB4bWF4ID0gMS4wMDEwNTc5NywgeW1pbj0tSW5mICwgeW1heD1JbmYsIGFscGhhPTAuNCwgY29sb3I9TkEsbGluZXR5cGUgPSAyLCBmaWxsPSIjOTk5OTk5IikgKwogICAgICAjIyBtYWtlIHByZXR0aWVyCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArCiAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNiwgZmFtaWx5PSJBcmlhbCIpKSArIAogICAgICAjIyBjaGFuZ2UgYXhpcyBsYWJlbHMKICAgICAgbGFicyh5ID0gVGVYKCIkR2Vub3R5cGVcIFxcbGVmdChcXGZyYWN7bl97bWFsZX19e25fe2ZlbWFsZX19XFxyaWdodCkkIikpICsKICAgICAgI2xhYnMoeSA9IGV4cHJlc3Npb24ocGFzdGUoIkdlbm90eXBlIiwgZ3JvdXAoIigiLCBmcmFjKHBhc3RlKCJuIG1hbGUiKSwgIm4gZmVtYWxlIiksICIpIikpKSkgKwogICAgICB4bGFiKGV4cHJlc3Npb24ocGFzdGUoIlNleCBSYXRpbyAoIiwgbG9nWzEwXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCgiKCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJhYyhwYXN0ZSgibiBtYWxlICsgMC4xIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIm4gZmVtYWxlICsgMC4xIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIpIiksICIpIiApKSkgKwogICAgICAjIyBjaGFuZ2UgY29sb3VycyBvZiBsb2xsaXBvcHMKICAgICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCIjYTUyYjFlIiwgIiMwMTZjMDAiKSkgKwogICAgICAjIyBhbm5vdGF0ZSBwaGVub3R5cGVzCiAgICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSA1LjUpKSAjKwogICAgICAjZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDE0LjUpKQoKcHJpbnQoc2V4X3JhdGlvX3Bsb3QpCgojIyMgQ0hBTkdFIFRPIEJJRyBCUkFDS0VUIEhFUkU6IGh0dHBzOi8vd3d3Lm92ZXJsZWFmLmNvbS9sZWFybi9sYXRleC9CcmFja2V0c19hbmRfUGFyZW50aGVzZXMgCgojcGFzdGUoIlNleCBSYXRpbyIsICJcbiIsICJsb2cxMCgobiBtYWxlICsgMC4xKS8obiBmZW1hbGUgKyAwLjEpKSIpCiN0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTYsIGZhbWlseT0iQXJpYWwiKSkKCiMjIGZyYWN0aW9uIHRpdGxlczogaHR0cHM6Ly9ncm91cHMuZ29vZ2xlLmNvbS9mb3J1bS8jIXRvcGljL2dncGxvdDIvYmdOUm5aODJoSlkgCiMjIGh0dHBzOi8vdWMtci5naXRodWIuaW8vbG9sbGlwb3AKCiNnZ3NhdmUoZmlsZW5hbWUgPSAiLi4vaW1hZ2VzX3RvX2V4cG9ydC9zZXhfcmF0aW9fcGxvdC5wbmciLCBkZXZpY2UgPSAicG5nIiwgd2lkdGggPSA3LCBoZWlnaHQgPSA3LCB1bml0cyA9ICJpbiIpCmBgYAoKIyMgQi4gU0NNQVAgTWV0aG9kCgojIyMgQnVpbGQgdGhlIGluZGV4CgpgYGB7cn0KIyMjIE1ha2luZyBhbiBvcnRob2xvZyByZWZlcmVuY2UgaW5kZXgKCiMjIGxvYWQgaW4gbWNhIGRhdGEKI2NvdW50cyA8LSByZWFkLmNzdigiLi4vc2NtYXAvYWxscGIxMHhfY291bnRzLmNzdiIsIHJvdy5uYW1lcyA9IDEpCiNwaGVubyA8LSByZWFkLmNzdigiLi4vc2NtYXAvYWxscGIxMHhfcGhlbm8uY3N2IikKI2dncGxvdChwaGVubywgYWVzKHg9UEMyXzNkLCB5ID0gUEMzXzNkLGNvbG91cj1hYnNjbHVzdDMpKSArIGdlb21fcG9pbnQoKQoKIyMgbG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShzY21hcCkgI2h0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvaHRtbC9zY21hcC5odG1sIApsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KSAjCgojcHJlcCB0aGUgU0NFLCBpZiB3YXMgb3JpZ2luYWxseSBhIFN1ZXJhdCBvYmplY3QgbmVlZCB0aGUgZGZzIHRvIGJlIHJlZ3VsYXIgbWF0cmljZXMKI3BiX2ZpbHRlcmVkX3NjZV9vcnRoIDwtIHBiX2ZpbHRlcmVkX3NjZV9vcnRoWywgY29sRGF0YShwYl9maWx0ZXJlZF9zY2Vfb3J0aCkkYWJzY2x1c3QzICE9ICI4Il0KI3NjZSA8LSBwYl9maWx0ZXJlZF9zY2Vfb3J0aAojcGNhIDwtIHBsb3RQQ0Eoc2NlKQojcGNzIDwtIHBjYSRkYXRhCiN0YWJsZShyb3duYW1lcyhwY3MpPT1jb2xuYW1lcyhzY2UpKQojY29sRGF0YShzY2UpIDwtIGNiaW5kKGNvbERhdGEoc2NlKSwgcGNzKQojcm93RGF0YShzY2UpJGZlYXR1cmVfc3ltYm9sIDwtIHJvd0RhdGEoc2NlKSRnZW5lCgojIyBleHRyYWN0IGRhdGEgZnJvbSBTZXVyYXQKI2NlbGxzX3RlbnggPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbd2hpY2godGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkZXhwZXJpbWVudCA9PSAidGVueF81ayIpLCBdKQojdGVueC5qdXN0d3QuaW50ZWdyYXRlZC4xMGsgPC0gc3Vic2V0KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGNlbGxzID0gY2VsbHNfdGVueCkKY291bnRzID0gYXMubWF0cml4KEdldEFzc2F5RGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBzbG90ID0gImNvdW50cyIsIGFzc2F5ID0gIlJOQSIpKQpwaGVubyA9IGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEpCgojIyBhZGQgVU1BUCBjb29yZGluYXRlcwpkZl9zZXhfY2VsbF9lbWJlZGRpbmdzIDwtIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MpCnBoZW5vIDwtIGNiaW5kKHBoZW5vLCBkZl9zZXhfY2VsbF9lbWJlZGRpbmdzKQoKIyMgU2V0IHVwIG9iamVjdApzY2UgPC0gU2luZ2xlQ2VsbEV4cGVyaW1lbnQobGlzdChjb3VudHM9Y291bnRzKSwKICAgIGNvbERhdGE9RGF0YUZyYW1lKGxhYmVsPXBoZW5vKSwKICAgIHJvd0RhdGE9RGF0YUZyYW1lKGZlYXR1cmVfc3ltYm9sPXJvd25hbWVzKGNvdW50cykpKQpzY2UKCiMjIG1hbnVhbCBsb2dnaW5nCiNjb3VudHNfMSA8LSBhc3NheShzY2UsICJjb3VudHMiKQojbGlic2l6ZXMgPC0gY29sU3Vtcyhjb3VudHNfMSkKI3NpemUuZmFjdG9ycyA8LSBsaWJzaXplcy9tZWFuKGxpYnNpemVzKQojbG9nY291bnRzKHNjZSkgPC0gbG9nMih0KHQoY291bnRzXzEpL3NpemUuZmFjdG9ycykgKyAxKQojY291bnRzKHNjZSkgPC0gYXMubWF0cml4KGNvdW50cyhzY2UpKQojbG9nY291bnRzKHNjZSkgPC0gYXMubWF0cml4KGxvZ2NvdW50cyhzY2UpKQpsb2djb3VudHMoc2NlKSA8LSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHNsb3QgPSAiZGF0YSIsIGFzc2F5ID0gIlJOQSIpKQoKIyMgcmVtb3ZlIGZlYXR1cmVzIHdpdGggZHVwbGljYXRlZCBuYW1lcwpzY2UgPC0gc2NlWyFkdXBsaWNhdGVkKHJvd25hbWVzKHNjZSkpLCBdCgojIyBidWlsZCBzY21hcC1jZWxsIHJlZmVyZW5jZSBpbmRleCwgc2F2ZSB0aGlzIHJkcwpzY2UgPC0gc2VsZWN0RmVhdHVyZXMoc2NlLCBzdXBwcmVzc19wbG90ID0gRkFMU0UsIG5fZmVhdHVyZXMgPSAyMDAwKQp0YWJsZShyb3dEYXRhKHNjZSkkc2NtYXBfZmVhdHVyZXMpCnNldC5zZWVkKDEpCnNjZSA8LSBpbmRleENlbGwoc2NlLCBNID0gNTAsIGsgPSA4MCkKbmFtZXMobWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4KQpsZW5ndGgobWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNlbnRyb2lkcykKZGltKG1ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleCRzdWJjZW50cm9pZHNbWzFdXSkKbWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNlbnRyb2lkc1tbMV1dWywxOjVdCmRpbShtZXRhZGF0YShzY2UpJHNjbWFwX2NlbGxfaW5kZXgkc3ViY2x1c3RlcnMpCgojc2F2ZVJEUyhwYl9maWx0ZXJlZF9zY2Vfb3J0aCwgZmlsZT0icGJfZmlsdGVyZWRfc2NlX29ydGhpbmRleF8yMDE4MTEwOS5yZHMiKQpgYGAKCiMjIyBNYXAgdG8gdGhlIGluZGV4CgpgYGB7cn0KI3Jvd0RhdGEocGJfZmlsdGVyZWRfc2NlX29ydGgpJGZlYXR1cmVfc3ltYm9sIDwtIHJvd0RhdGEocGJfZmlsdGVyZWRfc2NlX29ydGgpJG9ydGhfbmFtZQojcm93bmFtZXMocGJfZmlsdGVyZWRfc2NlX29ydGgpIDwtIHJvd0RhdGEocGJfZmlsdGVyZWRfc2NlX29ydGgpJG9ydGhfbmFtZQoKI3ByZXAgdGhlIFNDRSwgaWYgd2FzIG9yaWdpbmFsbHkgYSBTdWVyYXQgb2JqZWN0IG5lZWQgdGhlIGRmcyB0byBiZSByZWd1bGFyIG1hdHJpY2VzCiNwYl9maWx0ZXJlZF9zY2Vfb3J0aCA8LSBwYl9maWx0ZXJlZF9zY2Vfb3J0aFssIGNvbERhdGEocGJfZmlsdGVyZWRfc2NlX29ydGgpJGFic2NsdXN0MyAhPSAiOCJdCiNzY2UgPC0gcGJfZmlsdGVyZWRfc2NlX29ydGgKI3BjYSA8LSBwbG90UENBKHNjZSkKI3BjcyA8LSBwY2EkZGF0YQojdGFibGUocm93bmFtZXMocGNzKT09Y29sbmFtZXMoc2NlKSkKCiNjb2xEYXRhKHNjZSkgPC0gY2JpbmQoY29sRGF0YShzY2UpLCBwY3MpCgptdXRhbnRzX2NvdW50cyA9IGFzLm1hdHJpeChHZXRBc3NheURhdGEobXV0YW50X3NldXJhdCwgc2xvdCA9ICJjb3VudHMiLCBhc3NheSA9ICJSTkEiKSkKbXV0YW50c19waGVubyA9IGFzLmRhdGEuZnJhbWUobXV0YW50X3NldXJhdEBtZXRhLmRhdGEpCgojcm93RGF0YShzY2UpJGZlYXR1cmVfc3ltYm9sIDwtIHJvd0RhdGEoc2NlKSRnZW5lCm11dGFudHMuc2NlIDwtIFNpbmdsZUNlbGxFeHBlcmltZW50KGxpc3QoY291bnRzPW11dGFudHNfY291bnRzKSwKICAgIGNvbERhdGE9RGF0YUZyYW1lKGxhYmVsPW11dGFudHNfcGhlbm8pLAogICAgcm93RGF0YT1EYXRhRnJhbWUoZmVhdHVyZV9zeW1ib2w9cm93bmFtZXMobXV0YW50c19jb3VudHMpKSkKbXV0YW50cy5zY2UKCiMjIGFkZCBsb2cgY291bnRzCiMjIG1hbnVhbAojY291bnRzXzEgPC0gYXNzYXkobXV0YW50cy5zY2UsICJjb3VudHMiKQojbGlic2l6ZXMgPC0gY29sU3Vtcyhjb3VudHNfMSkKI3NpemUuZmFjdG9ycyA8LSBsaWJzaXplcy9tZWFuKGxpYnNpemVzKQojbG9nY291bnRzKG11dGFudHMuc2NlKSA8LSBsb2cyKHQodChjb3VudHNfMSkvc2l6ZS5mYWN0b3JzKSArIDEpCiMjIGZyb20gc2V1cmF0CmxvZ2NvdW50cyhtdXRhbnRzLnNjZSkgPC0gYXMubWF0cml4KEdldEFzc2F5RGF0YShtdXRhbnRfc2V1cmF0LCBzbG90ID0gImRhdGEiLCBhc3NheSA9ICJSTkEiKSkKCiNQcm9qZWN0IHF1ZXJ5IGRhdGEgc2V0IG9udG8gY2VsbCBpbmRleApzY21hcENlbGxfcmVzdWx0cyA8LSBzY21hcENlbGwoCiAgbXV0YW50cy5zY2UsIAogIGxpc3Qod3QgPSBtZXRhZGF0YShzY2UpJHNjbWFwX2NlbGxfaW5kZXgKICApCikKCiMjTG9vayBpbnRvIHRoZSByZXN1bHRzCiMgRm9yIGVhY2ggZGF0YXNldCB0aGVyZSBhcmUgdHdvIG1hdHJpY2llcy4gY2VsbHMgbWF0cml4IGNvbnRhaW5zIHRoZSB0b3AgMTAgKHNjbWFwIGRlZmF1bHQpIGNlbGwgSURzIG9mIHRoZSBjZWxscyBvZiB0aGUgcmVmZXJlbmNlIGRhdGFzZXQgdGhhdCBhIGdpdmVuIGNlbGwgb2YgdGhlIHByb2plY3Rpb24gZGF0YXNldCBpcyBjbG9zZXN0IHRvOgojICAgCiMgICBHaXZlIGFzc2lnbm1lbnRzIGluIHR3byB3YXlzOgojICAgMS4gVGFrZSB0aGUgdG9wIGNlbGwgYXNzaWdubWVudCBhYnMgY2x1c3QsIGlmIGNvc2luZSBzaW1pbGFyaXR5IGlzIGxlc3MgdGhhbiAwLjQgKG9yIGFkanVzdCBpZiBuZWVkZWQpIG1hcmsgYXMgdW5hc3NpZ25lZAojIDIuIEZvciB0aGUgdG9wIDMgbmVhcmVzdCBuZWlnaGJvcnMsIGdldCBhIG1lYW4gb2YgdGhlIFBDQSBjb29yZGluYXRlcyBhbmQgc25hcCB0byB0aGUgbmVhcmVzdCBjZWxsIG9mIHRob3NlIGNvb3JkaW5hdGVzLiBJZiBhbnkgb2YgdGhlIHRvcCB0aHJlZSBjZWxscyBhcmUgc2ltIGJlbG93IDAuNCB0aGVuIG1hcmsgYXMgdW5hc3NpZ25lZC4KCgojI1RvcCBjZWxsIGFzc2lnbm1lbnQgbWV0aG9kCgojIyBsb29rIGF0IGFzc2lnbm1lbnRzCnNjbWFwQ2VsbF9yZXN1bHRzJHd0JGNlbGxzWywgMTozXQojIyBnZXQgY2VsbCBpbmRleGVzIApnZXRjZWxscyA8LSBzY21hcENlbGxfcmVzdWx0cyR3dCRjZWxsc1sxLCBdCiMjIGV4Y3RyYWN0IGNlbGxzIG1ldGFkYXRhIGZyb20gaW5kZXgKY2RzY2UgPC0gY29sRGF0YShzY2UpW2dldGNlbGxzLCBdCiMjIGV4dHJhY3Qgc2ltaWxhcml0aWVzCnRvcHNpbSA8LSBzY21hcENlbGxfcmVzdWx0cyR3dCRzaW1pbGFyaXRpZXNbMSwgXQojIyBnZXQgbmFtZSBvZiB0b3AgY2VsbCBtYXRjaGVkCm11dGFudHMuc2NlJHRvcGNlbGwgPC0gcm93bmFtZXMoY2RzY2UpCiMjIGdldCBzZXggaWQKbXV0YW50cy5zY2UkdG9wY2VsbF9hYyA8LSBjZHNjZSRsYWJlbC5tb25vY2xlX3NleAojIyBnZXQgY29vcmRpbmF0ZXMgb2YgbWF0Y2hlZCBjZWxsCm11dGFudHMuc2NlJGluZGV4UEMxIDwtIGNkc2NlJGxhYmVsLlVNQVBfMQptdXRhbnRzLnNjZSRpbmRleFBDMiA8LSBjZHNjZSRsYWJlbC5VTUFQXzIKI211dGFudHMuc2NlJHBicHQgPC0gY2RzY2UkcHNldWRvdGltZQojbXV0YW50cy5zY2UkcGJidWxrIDwtIGNkc2NlJGJ1bGsKbXV0YW50cy5zY2UkdG9wY2VsbF9zcCA8LSBtdXRhbnRzLnNjZSR0b3BjZWxsX2FjCm11dGFudHMuc2NlJHRvcHNpbSA8LSB0b3BzaW0KbXV0YW50cy5zY2UkdG9wY2VsbF9zcFttdXRhbnRzLnNjZSR0b3BzaW0gPCAwLjRdIDwtICJ1bmFzc2lnbmVkIgp0YWJsZShtdXRhbnRzLnNjZSR0b3BjZWxsX3NwKQpgYGAKCmBgYHtyfQojIyBzZWUgaG93IHRoaXMgb3ZlcmxhcHMgd2l0aCBmbHVvcmVzY2VuY2Ugc29ydGVkIG9uIGZvciA4MjAgdG8gY29uZmlybSBhY2N1cmFjeQpkZl84MjAgPC0gY29sRGF0YShtdXRhbnRzLnNjZSlbY29sRGF0YShtdXRhbnRzLnNjZSkkbGFiZWwuZ2VuZXRpY19iYWNrZ3JvdW5kID09IlBCQU5LQV84MjAiLCBdCnRhYmxlKGRmXzgyMCR0b3BjZWxsX3NwLCBkZl84MjAkbGFiZWwuZmx1b3Jlc2VuY2Vfc29ydGVkX29uKQpgYGAKCmBgYHtyfQp0YWJsZShjb2xEYXRhKG11dGFudHMuc2NlKSR0b3BjZWxsX3NwLCBjb2xEYXRhKG11dGFudHMuc2NlKSRsYWJlbC5pZGVudGl0eV9uYW1lX3VwZGF0ZWQpCmBgYAoKCmBgYHtyfQojIyMjIFRPUCAzTk4gbWV0aG9kCgojVGhpcyBmdW5jdGlvbiBtYWtlcyBhIGxpc3Qgb2YgdGhlIFBDIG1lYW5zIGZvciBlYWNoIGNlbGwgYW5kIHRoZW4gZG8uY2FsbCBiZWxvdyByYmluZHMgdGhlbSBpbnRvIGEgZGF0YWZyYW1lIGNhbGxlZCBiaWdfZGF0YQoKZGF0YWxpc3QgPSBsaXN0KCkKCmZvciAoaSBpbiBjb2xuYW1lcyhzY21hcENlbGxfcmVzdWx0cyR3dCRjZWxscykpIHsKICAKICBnZXRjZWxsc3Rlc3QgPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3QkY2VsbHNbMTozLCBpXQogIGNkc2NldGVzdCA8LSBjb2xEYXRhKHNjZSlbZ2V0Y2VsbHN0ZXN0LCBdCiAgUEMxbWVhbiA8LSBtZWFuKGNkc2NldGVzdCRsYWJlbC5VTUFQXzEpCiAgUEMybWVhbiA8LSBtZWFuKGNkc2NldGVzdCRsYWJlbC5VTUFQXzIpCiAgIyAuLi4gbWFrZSBzb21lIGRhdGEKICBkYXQgPC0gZGF0YS5mcmFtZShpLCBQQzFtZWFuLCBQQzJtZWFuKQogIGRhdCRpIDwtIGkgICMgbWF5YmUgeW91IHdhbnQgdG8ga2VlcCB0cmFjayBvZiB3aGljaCBpdGVyYXRpb24gcHJvZHVjZWQgaXQ/CiAgZGF0YWxpc3RbW2ldXSA8LSBkYXQgIyBhZGQgaXQgdG8geW91ciBsaXN0Cn0KCmJpZ19kYXRhID0gZG8uY2FsbChyYmluZCwgZGF0YWxpc3QpCiMgb3IgYmlnX2RhdGEgPC0gZHBseXI6OmJpbmRfcm93cyhkYXRhbGlzdCkKIyBvciBiaWdfZGF0YSA8LSBkYXRhLnRhYmxlOjpyYmluZGxpc3QoZGF0YWxpc3QpCgp0ZXN0IDwtIGJpZ19kYXRhWzEsIF0KCmRmIDwtIGRhdGEuZnJhbWUoWD1jb2xEYXRhKHNjZSkkbGFiZWwuVU1BUF8xLCBZPWNvbERhdGEoc2NlKSRsYWJlbC5VTUFQXzIsIHJvdy5uYW1lcyA9IHJvd25hbWVzKGNvbERhdGEoc2NlKSkpCgojdGhlIHNuYXAgZnVuY3Rpb24gc25hcHMgdG8gdGhlIG5lYXJlc3QgY2VsbCBpbiBQQyBjb29yZGlhbnRlcwpzbmFwIDwtIGZ1bmN0aW9uKGRmLCB0ZXN0KXsKICByZXF1aXJlKEJpb2Jhc2UpCiAgZCA8LSBtYXRjaHB0KGFzLm1hdHJpeChkZiksCiAgICAgICAgICAgICAgIGFzLm1hdHJpeChkYXRhLmZyYW1lKFg9dGVzdCRQQzFtZWFuLFk9dGVzdCRQQzJtZWFuKSkpCiAgCiAgbWluX3JvdyA8LSByb3duYW1lcyhkW2QkZGlzdGFuY2U9PW1pbihkJGRpc3RhbmNlKSxdKQogIAogIHRlc3QkWF9zbmFwIDwtIHVuaXF1ZShkZlttaW5fcm93LCJYIl0pCiAgdGVzdCRZX3NuYXAgPC0gdW5pcXVlKGRmW21pbl9yb3csIlkiXSkKICB0ZXN0JHBiX2NlbGwgPC0gbWluX3JvdwogIAogIHRlc3QKfQoKI3RoaXMgbG9vcHMgdGhyb3VnaCBlYWNoIGNlbGwgYW5kIGluIGJpZ19kYXRhIGFuZCBydW5zIHRoZSBzbmFwIGZ1bmN0aW9uCmRhdGFsaXN0MiA9IGxpc3QoKQpjb2xuYW1lcyhiaWdfZGF0YSkgPC0gYygic2FtcGxlX2lkIiwgIlBDMW1lYW4iLCAiUEMybWVhbiIpCmZvciAoaSBpbiByb3duYW1lcyhiaWdfZGF0YSkpIHsKICB0ZXN0IDwtIGJpZ19kYXRhW2ksIF0KICBjb29yZCA8LSBzbmFwKGRmLCB0ZXN0KQogIGNvb3JkJGkgPC0gaQogIGRhdGFsaXN0MltbaV1dIDwtIGNvb3JkCn0KYmlnX2RhdGEyID0gZG8uY2FsbChyYmluZCwgZGF0YWxpc3QyKQoKCnRhYmxlKHJvd25hbWVzKGJpZ19kYXRhMik9PXJvd25hbWVzKGNvbERhdGEobXV0YW50cy5zY2UpKSkKCmFsbHBiY2QgPC0gY29sRGF0YShzY2UpCmFsbHBiY2QgPC0gYXMuZGF0YS5mcmFtZShhbGxwYmNkKQpwYmFic2NsdXN0IDwtIGFsbHBiY2RbLCBjKCJsYWJlbC5wdF9pZF9jb2xzIiwgImxhYmVsLmlkZW50aXR5X25hbWVfdXBkYXRlZCIsICJsYWJlbC5tb25vY2xlX3NleCIpLCBkcm9wPUZBTFNFXQpwYmFic2NsdXN0JHBiX3NhbXBsZV9pZCA8LSByb3duYW1lcyhwYmFic2NsdXN0KQoKIyBOb3cgbWVyZ2UgdGhlIHBjIGNlbGwgYXNpZ25tZW50cyB3aXRoIHRoZWlyIGFicyBjbHVzdCBhbmQgZ2V0IGluIHRoZSByaWdodCBvcmRlcgpiaWdfZGF0YTMgPC0gbWVyZ2UoYmlnX2RhdGEyLCBwYmFic2NsdXN0LCBieS54ID0gInBiX2NlbGwiLCBieS55ID0gInBiX3NhbXBsZV9pZCIsIGFsbC54PVRSVUUsIGFsbC55PUZBTFNFKQpiaWdfZGF0YTQgPC0gYmlnX2RhdGEzW21hdGNoKHJvd25hbWVzKGJpZ19kYXRhMiksIGJpZ19kYXRhMyRzYW1wbGVfaWQpLCBdCgoKY29sb3JzIDwtIGMoIjYiPSIjNzhDNjc5IiwKICAgICAgICAgICAgIjIiPSIjRDFFQzlGIiwKICAgICAgICAgICAgIjAiPSIjRkVCMjRDIiwKICAgICAgICAgICAgIjEiPSIjRjRDRjYzIiwKICAgICAgICAgICAgIjMiPSIjRkVFRUFBIiwKICAgICAgICAgICAgIjQiPSIjODVCMUQzIiwKICAgICAgICAgICAgIjciPSIjOWVjYWUxIiwKICAgICAgICAgICAgIjUiPSIjQzlFOEYxIiwKICAgICAgICAgICAgIk0iPSAiI0I3QjdEOCIsCiAgICAgICAgICAgICJGIj0iIzlDOTZDNiIsCiAgICAgICAgICAgICJ1bmFzc2lnbmVkIj0iYmxhY2siKQoKZ2dwbG90KGJpZ19kYXRhNCwgYWVzKFBDMW1lYW4sIFBDMm1lYW4pKSArCiAgZ2VvbV9wb2ludChjb2wgPSBiaWdfZGF0YTQkbGFiZWwucHRfaWRfY29scykgKwogICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKwogICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpCgojKyBnZW9tX3BvaW50KGFlcyhjb2xvdXI9ZmFjdG9yKGJpZ19kYXRhNCRsYWJlbC5sYWJlbC5wdF9pZF9jb2xzKSkpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9ycykgCgogICAgICAgICAgICAgICAgICAgICAKCmdncGxvdChiaWdfZGF0YTQsIGFlcyhYX3NuYXAsIFlfc25hcCkpICsKICBnZW9tX3BvaW50KGNvbCA9IGJpZ19kYXRhNCRsYWJlbC5wdF9pZF9jb2xzKSArCiAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgCgojKyBnZW9tX3BvaW50KGFlcyhjb2xvdXI9ZmFjdG9yKGJpZ19kYXRhNCRsYWJlbC5sYWJlbC5wdF9pZF9jb2xzKSkpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9ycykgCgojI2FkZCBpbmZvIHRvIFNDRSBhbmQgc2F2ZSBjb2xEYXRhLCB0byBiZSBhbiBhc3NpZ25lZCBjZWxsIGFsbCAzTk4gbXVzdCBoYXZlIGEgY29zIHNpbSA+MC40CnNjbWFwQ2VsbF9yZXN1bHRzJHd0JHNpbWlsYXJpdGllc1ssIDE6M10KdG9wc2ltMSA8LSBzY21hcENlbGxfcmVzdWx0cyR3dCRzaW1pbGFyaXRpZXNbMSwgXQp0b3BzaW0yIDwtIHNjbWFwQ2VsbF9yZXN1bHRzJHd0JHNpbWlsYXJpdGllc1syLCBdCnRvcHNpbTMgPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3Qkc2ltaWxhcml0aWVzWzMsIF0KCnRhYmxlKGJpZ19kYXRhNCRzYW1wbGVfaWQ9PXJvd25hbWVzKGNvbERhdGEobXV0YW50cy5zY2UpKSkKI3Bmb2JqJHBiX2NlbGwgPC0gYmlnX2RhdGE0JHBiX2NlbGwKI3Bmb2JqJFBDMW1lYW4gPC0gYmlnX2RhdGE0JFBDMW1lYW4KYmQ0IDwtIGJpZ19kYXRhNFssIGMoInBiX2NlbGwiLCAic2FtcGxlX2lkIiwgIlBDMW1lYW4iLCAiUEMybWVhbiIsICJYX3NuYXAiLCAiWV9zbmFwIiwgImxhYmVsLnB0X2lkX2NvbHMiLCAibGFiZWwuaWRlbnRpdHlfbmFtZV91cGRhdGVkIiwgImxhYmVsLm1vbm9jbGVfc2V4IildCgpjb2xEYXRhKG11dGFudHMuc2NlKSA8LSBjYmluZChjb2xEYXRhKG11dGFudHMuc2NlKSwgYmQ0KQoKbXV0YW50cy5zY2UkdG9wc2ltMSA8LSB0b3BzaW0xCm11dGFudHMuc2NlJHRvcHNpbTIgPC0gdG9wc2ltMgptdXRhbnRzLnNjZSR0b3BzaW0zIDwtIHRvcHNpbTMKbXV0YW50cy5zY2Ukc3RhZ2VfcHJlZCA8LSBiaWdfZGF0YTQkbGFiZWwubW9ub2NsZV9zZXgKbXV0YW50cy5zY2Ukc3RhZ2VfcHJlZFttdXRhbnRzLnNjZSR0b3BzaW0xIDwgMC40IHwgbXV0YW50cy5zY2UkdG9wc2ltMiA8IDAuNCB8IG11dGFudHMuc2NlJHRvcHNpbTMgPCAwLjRdIDwtICJ1bmFzc2lnbmVkIgp0YWJsZShtdXRhbnRzLnNjZSRzdGFnZV9wcmVkKQoKI3dyaXRlLmNzdihiZDQsICJwZmNlbGxhc3NpZ25tZW50c3dpdGhtZWFuM25uXzIwMTgxMDI5LmNzdiIpCiN3cml0ZS5jc3YoY29sRGF0YShwZm9iaiksICJwZjNkNzEwMHNjbWFwY2x1c3RzMm1ldGhvZGluZGV4bjEwMF8yMDE5MDEwNy5jc3YiKQpgYGAKCmBgYHtyfQojIyBzZWUgaG93IHRoaXMgb3ZlcmxhcHMgd2l0aCBmbHVvcmVzY2VuY2Ugc29ydGVkIG9uIGZvciA4MjAgdG8gY29uZmlybSBhY2N1cmFjeQpkZl84MjAgPC0gY29sRGF0YShtdXRhbnRzLnNjZSlbY29sRGF0YShtdXRhbnRzLnNjZSkkbGFiZWwuZ2VuZXRpY19iYWNrZ3JvdW5kID09IlBCQU5LQV84MjAiLCBdCnRhYmxlKGRmXzgyMCRzdGFnZV9wcmVkLCBkZl84MjAkbGFiZWwuZmx1b3Jlc2VuY2Vfc29ydGVkX29uKQpgYGAKCmBgYHtyfQp0YWJsZShjb2xEYXRhKG11dGFudHMuc2NlKSRzdGFnZV9wcmVkLCBjb2xEYXRhKG11dGFudHMuc2NlKSRsYWJlbC5pZGVudGl0eV9uYW1lX3VwZGF0ZWQpCmBgYAoKCiMjIG1ha2UgZmluYWwgcGxvdCB3aXRoIE1DQSBkYXRhIGJlbG93CmBgYHtyfQojIyBSZWFkIGluIE1DQSBkYXRhCnBoZW5vIDwtIHJlYWQuY3N2KCIuLi9zY21hcC9hbGxwYjEweF9waGVuby5jc3YiKQojIyBleHRyYWN0IHJvd3MgbmVlZGVkIGZvciBwbG90dGluZwpkZl9wbG90IDwtIHBoZW5vWyxjKCJQQzJfM2QiLCAiUEMzXzNkIiwgImFic2NsdXN0MyIpXQpkZl9wbG90JGV4cGVyaW1lbnQgPC0gZGZfcGxvdCRhYnNjbHVzdDMKCiMjIGV4dHJhY3Qgcm93cyBuZWVkZWQgZm9yIHBsb3R0aW5nIGZyb20gbWFwcGVkIG9iamVjdApkZl9wbG90X3BtIDwtIGFzLmRhdGEuZnJhbWUoY29sRGF0YShwbV9zczJfZmllbGQuc2NlLm9ydGgpKQpkZl9wbG90X3BtIDwtIGRmX3Bsb3RfcG1bICxjKCJYX3NuYXAiLCAiWV9zbmFwIiwgImxhYmVsLmFic2NsdXN0MyIpXQpkZl9wbG90X3BtJGV4cGVyaW1lbnQgPC0gInBtIgpjb2xuYW1lcyhkZl9wbG90X3BtKSA8LSBjKCJQQzJfM2QiLCAiUEMzXzNkIiwgImFic2NsdXN0MyIsICJleHBlcmltZW50IikKCiMjIGV4dHJhY3Qgcm93cyBuZWVkZWQgZm9yIHBsb3R0aW5nIGZyb20gbWFwcGVkIG9iamVjdApkZl9wbG90X3BmIDwtIGFzLmRhdGEuZnJhbWUoY29sRGF0YShwZl9zczJfZmllbGQuc2NlLm9ydGgpKQpkZl9wbG90X3BmIDwtIGRmX3Bsb3RfcGZbICxjKCJYX3NuYXAiLCAiWV9zbmFwIiwgImxhYmVsLmFic2NsdXN0MyIpXQpkZl9wbG90X3BmJGV4cGVyaW1lbnQgPC0gInBmIgpjb2xuYW1lcyhkZl9wbG90X3BmKSA8LSBjKCJQQzJfM2QiLCAiUEMzXzNkIiwgImFic2NsdXN0MyIsICJleHBlcmltZW50IikKCiMjIGJpbmQgdG9nZXRoZXIKZGZfcGxvdCA8LSByYmluZChkZl9wbG90LCBkZl9wbG90X3BmLCBkZl9wbG90X3BtKQoKY29sb3JzIDwtIGMoIjYiPSIjNzhDNjc5IiwKICAgICAgICAgICAgIjIiPSIjRDFFQzlGIiwKICAgICAgICAgICAgIjAiPSIjRkVCMjRDIiwKICAgICAgICAgICAgIjEiPSIjRjRDRjYzIiwKICAgICAgICAgICAgIjMiPSIjRkVFRUFBIiwKICAgICAgICAgICAgIjQiPSIjODVCMUQzIiwKICAgICAgICAgICAgIjciPSIjOWVjYWUxIiwKICAgICAgICAgICAgIjUiPSIjQzlFOEYxIiwKICAgICAgICAgICAgIk0iPSAiI0I3QjdEOCIsCiAgICAgICAgICAgICJGIj0iIzlDOTZDNiIsCiAgICAgICAgICAgICJ1bmFzc2lnbmVkIj0iYmxhY2siLAogICAgICAgICAgICAicG0iID0gIiNkYzY1YTQiLAogICAgICAgICAgICAicGYiID0gIiMyNDI0NWYiKQoKIyMgYWRkIGFscGhhIGZvciBwbG90dGluZwpkZl9wbG90JGFscGhhWyFkZl9wbG90JGV4cGVyaW1lbnQgPT0gInBtIl0gPC0gMC41CmRmX3Bsb3QkYWxwaGFbZGZfcGxvdCRleHBlcmltZW50ID09ICJwbSJdIDwtIDEKZGZfcGxvdCRhbHBoYVtkZl9wbG90JGV4cGVyaW1lbnQgPT0gInBmIl0gPC0gMQoKIyNwbG90CnNjbWFwX3BjYSA8LSBnZ3Bsb3QoZGZfcGxvdCwgYWVzKHg9UEMyXzNkLCB5ID0gUEMzXzNkLGNvbG91cj1leHBlcmltZW50LCBhbHBoYSA9IGFscGhhKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9ycykgKwogICMjIHJlbW92ZSBhbHBoYSBzY2FsZQogIHNjYWxlX2FscGhhX2NvbnRpbnVvdXMoZ3VpZGU9RkFMU0UpCiAgIyMgZHJhdyByaW5nIGFyb3VuZCBmaWVsZCBzYW1wbGVzCiAgI2dlb21fcG9pbnQoZGF0YT1kZl9wbG90W2RmX3Bsb3QkZXhwZXJpbWVudCA9PSAicG0iLCBdLCBwY2g9MjEsIGZpbGw9TkEsIHNpemU9MiwgY29sb3VyPSJibGFjayIsIHN0cm9rZT0xKSArCiAgIyMgbWFrZSBub24tZmllbGQgc2FtcGxlcyBtb3JlIG9wYXF1ZQogICNnZW9tX3BvaW50KGRhdGE9ZGZfcGxvdFstZGZfcGxvdCRleHBlcmltZW50ID09ICJwbSIsIF0sIGFscGhhID0gMC4yKQoKIyMgdmlldwpzY21hcF9wY2FfMiA8LSBzY21hcF9wY2EgKyAKICBndWlkZXMoY29sb3VyPWd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NCkpKQoKc2NtYXBfcGNhXzIKYGBgCgpzYXZlCmBgYHtyfQojZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L2ZpZWxkX3NhbXBsZXNfc2NtYXAucG5nIiwgcGxvdCA9IHNjbWFwX3BjYV8yLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAxNSwgaGVpZ2h0ID0gMTAsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMjIE92ZXJsYXAgYW5kIHZhbGlkYXRpb24KCmBgYHtyfQoKYGBgCgpgYGB7cn0KCmBgYAoKIyAxMS4gU2F2ZSBhbmQgRXhwb3J0IHsudGFic2V0fQoKIyMgc2F2ZQoKU2F2ZSBlbnZpcm9ubWVudApgYGB7cn0KIyMgVGhpcyBzYXZlcyBldmVyeXRoaW5nIGluIHRoZSBnbG9iYWwgZW52aXJvbm1lbnQgZm9yIGVhc3kgcmVjYWxsIGxhdGVyCiNzYXZlLmltYWdlKGZpbGUgPSAiR0NTS09fbWVyZ2UuUkRhdGEiKQojbG9hZChmaWxlID0gIkdDU0tPX21lcmdlLlJEYXRhIikKYGBgCgpTYXZlIG9iamVjdChzKQpgYGB7cn0KIyMgU2F2ZSBhbiBvYmplY3QgdG8gYSBmaWxlCnNhdmVSRFModGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgsIGZpbGUgPSAiLi4vZGF0YV90b19leHBvcnQvdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXguUkRTIikKIyMgUmVzdG9yZSB0aGUgb2JqZWN0CiNyZWFkUkRTKGZpbGUgPSAiLi4vZGF0YV90b19leHBvcnQvdGVueC5tdXRhbnQuaW50ZWdyYXRlZC5zZXguUkRTIikKCiMjIHNhdmUgaW50ZWdyYXRlZCBvYmplY3QgdG8gZmlsZQpzYXZlUkRTKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZpbGUgPSAiLi4vZGF0YV90b19leHBvcnQvdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5SRFMiKSAKIyMgcmVzdG9yZSB0aGUgb2JqZWN0CiN0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIHJlYWRSRFMoIi4uL2RhdGFfdG9fZXhwb3J0L3RlbnguanVzdHd0LmludGVncmF0ZWQuUkRTIikKCiMjIHNhdmUgbW9ub2NsZSBvYmplY3QKc2F2ZVJEUyhtb25vY2xlLm9iamVjdC5hbGwsIGZpbGUgPSAiLi4vZGF0YV90b19leHBvcnQvbW9ub2NsZS5vYmplY3QuYWxsLlJEUyIpIAojIyByZXN0b3JlIHRoZSBvYmplY3QKI21vbm9jbGUub2JqZWN0LmFsbCA8LSByZWFkUkRTKCIuLi9kYXRhX3RvX2V4cG9ydC9tb25vY2xlLm9iamVjdC5hbGwuUkRTIikKCiMjIHNhdmUgaW50ZWdyYXRlZCBvYmplY3QgdG8gZmlsZQojc2F2ZVJEUyhHQ1NLT19tdXRhbnRzLCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L0dDU0tPX211dGFudHMuUkRTIikgCiMjIHJlc3RvcmUgdGhlIG9iamVjdAojdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSByZWFkUkRTKCIuLi9kYXRhX3RvX2V4cG9ydC90ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLlJEUyIpCmBgYAoKQ2xlYW4gdXAKYGBge3J9CiNybShzczJfd3RfY2VsbHMpCiNybSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKQojcm0odGVueC5qdXN0d3QubGlzdCkKYGBgCgojIyBmaW5hbCBmaWd1cmUgY29uc3RydWN0aW9uCgpbQ293cGxvdF0oaHR0cHM6Ly93aWxrZWxhYi5vcmcvY293cGxvdC9hcnRpY2xlcy9wbG90X2dyaWQuaHRtbCkocGxvdF9ncmlkKSwgW3BhdGNod29ya10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BhdGNod29yay92aWduZXR0ZXMvcGF0Y2h3b3JrLmh0bWwpKHdyYXBfcGxvdHMpLCBhbmQgW2dncHVicl0oaHR0cDovL3d3dy5zdGhkYS5jb20vZW5nbGlzaC9hcnRpY2xlcy8yNC1nZ3B1YnItcHVibGljYXRpb24tcmVhZHktcGxvdHMvODEtZ2dwbG90Mi1lYXN5LXdheS10by1taXgtbXVsdGlwbGUtZ3JhcGhzLW9uLXRoZS1zYW1lLXBhZ2UvKSBjYW4gYWxsIGFsbG93IG11bHRpcGxlIHBsb3RzIHRvIGJlIHBsb3R0ZWQgdG9nZXRoZXIuIAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMS43LCBmaWcud2lkdGggPSA4LjN9CiMjIEEKIyB1bWFwX2lkX3B0CiMjIEIKIyBtYXJrZXIgZ2VuZSBleHByZXNzaW9uCiMjIEMKIyBNdXRhbnQgZ2VuZSBleHByZXNzaW9uCiMjIEQKIyBNb2R1bGVzCgojRmlndXJlX0EgPC0gZ3JpZC5hcnJhbmdlKGFycmFuZ2VHcm9iKFFDX2NvbXBvc2l0ZV9wbG90LCBRQ19taXRvX3Zpb2xpbiwgUUNfbWl0b19ncmFwaCwgUUNfYnlfZ2Vub3R5cGUsIG1hcHBpbmdfcmF0ZV9wbG90KSwgbnJvdz0zKSwgbnJvdz0yLCBoZWlnaHRzPWMoMTAsMikpCgojIyBjb3dwbG90IG1ldGhvZAojIyBjYW4gdXNlIHRoaXMgZm9yIGxhYmVsczogdG91cHBlcihsZXR0ZXJzKVsxOjEwXQoKIyMgQy4gTXV0YW50IGdlbmVzCm11dGFudF9nZW5lc19maWd1cmUgPC0gcGxvdF9ncmlkKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIyBtYXJrZXIgZ2VuZXMgc3RhcnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfRkFNQiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9NU1A4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X01TUDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfQVAyRywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9DQ1AyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X01HMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMgbXV0YW50IGdlbmVzIHN0YXJ0cyAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfZ2QxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X21kMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9tZDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfbWQzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X21kNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfbWQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X2ZkMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9mZDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfZmQzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X2ZkNCwgCiAgbGFiZWxfc2l6ZSA9IDEsIAogIG5yb3cgPSA0KQoKIyMgbGFiZWxzIGFzIHVwcGVyY2FzZSBsZXR0ZXJzOgojYyh0b3VwcGVyKGxldHRlcnMpWzI6MTddKQojIGxhYmVscyBhcyByb21hbiBudW1lcmFsczoKIyBjKHRvbG93ZXIoYXMucm9tYW4oYygyOjE3KSkKCkZpZ3VyZV9wdWJsaWNhdGlvbiA8LSBwbG90X2dyaWQodW1hcF9pZF9wdCArIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGFudF9nZW5lc19maWd1cmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIGVtcHR5IHBsb3QgdG8gZ2l2ZSBzcGFjaW5nCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyB0aGVtZV92b2lkKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygnQScsICdCJyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX3NpemUgPSAxMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5yb3c9MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDEsIDEsIDQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygxLCAyLCAzKSkKCkZpZ3VyZV9wdWJsaWNhdGlvbgpgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9GaWd1cmVfQy5wbmciLCBwbG90ID0gRmlndXJlX3B1YmxpY2F0aW9uLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMSwgaGVpZ2h0ID0gMjkuNywgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMS43LCBmaWcud2lkdGggPSA4LjN9CmxheW91dCA8LSAiCkFBQkIKREVGRwpISUpLCkxNTk8KUFFSUwoiCgpGaWd1cmVfcHVibGljYXRpb24gPC0gKGNvbXBvc2l0aW9uX3VtYXBfMTB4ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAxMCkpKSArCihjb21wb3NpdGlvbl91bWFwX3NzMiArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMTApKSkgKwojKFVNQVBfaG9vICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAxMCkpICsgbGFicyh0aXRsZT0iUHJlZGljdGVkIEFzZXh1YWwgQ3ljbGUgUmVhbCBUaW1lcG9pbnQiKSkgKwojKFVNQVBfa2FzaWEgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDEwKSkgKyBsYWJzKHRpdGxlPSJQcmVkaWN0ZWQgR2FtZXRvY3l0b2dlbmVzaXMgUmVhbCBUaW1lcG9pbnQiKSkgKwogICMjIG1hcmtlciBnZW5lcwptYXJrZXJfZ2VuZV9wbG90X0ZBTUIgKwptYXJrZXJfZ2VuZV9wbG90X01TUDggKwptYXJrZXJfZ2VuZV9wbG90X01TUDEgKwptYXJrZXJfZ2VuZV9wbG90X0FQMkcgKwptYXJrZXJfZ2VuZV9wbG90X0NDUDIgKwptYXJrZXJfZ2VuZV9wbG90X01HMSArCiAgIyMgbXV0YW50IGdlbmVzIHN0YXJ0cyAgCm1hcmtlcl9nZW5lX3Bsb3RfZ2QxICsKbWFya2VyX2dlbmVfcGxvdF9tZDEgKwptYXJrZXJfZ2VuZV9wbG90X21kMiArCm1hcmtlcl9nZW5lX3Bsb3RfbWQzICsKbWFya2VyX2dlbmVfcGxvdF9tZDQgKyAKbWFya2VyX2dlbmVfcGxvdF9tZDUgKwptYXJrZXJfZ2VuZV9wbG90X2ZkMSArCm1hcmtlcl9nZW5lX3Bsb3RfZmQyICsKbWFya2VyX2dlbmVfcGxvdF9mZDMgKwptYXJrZXJfZ2VuZV9wbG90X2ZkNCArIApwbG90X2xheW91dChuY29sID0gNCwgCiAgICAgICAgICAgIHdpZHRocyA9IGMoMSwgMSwgMSwgMSksCiAgICAgICAgICAgIGhlaWdodHMgPSBjKDIsIDEsIDEsIDEsIDEpLAogICAgICAgICAgICBkZXNpZ24gPSBsYXlvdXQKICAgICAgICAgICAgKQoKRmlndXJlX3B1YmxpY2F0aW9uCmBgYAoKc2F2ZQpgYGB7cn0KZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L0ZpZ3VyZV9TMi5wbmciLCBwbG90ID0gRmlndXJlX3B1YmxpY2F0aW9uLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMSwgaGVpZ2h0ID0gMjkuNywgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKIyBBcHBlbmRpeCB7LnRhYnNldH0KCiMjIFNlc3Npb24gSW5mbyAKYGBge3IsIGVjaG8gPSBGQUxTRX0Kc2Vzc2lvbkluZm8oKQpgYGAKCiMgRXhwcmVzc2lvbiBwbG90cwoKIyMjIyBFeHByZXNzaW9uIC0gcmF3IC0gVmlyaWRpcwpgYGB7ciwgZmlnLmhlaWdodCA9IDE1LCBmaWcud2lkdGggPSAxNX0KIyMgZmluZCBhIGdvb2QgcmluZyBtYXJrZXIsIHRvIHNlZSBpZiB0aGVyZSBpcyBhIGJldHRlciBvbmUgdGhhbiB0aGUgb25lcyByZXBvcnRlZAojbWFya2Vyc19yaW5nIDwtIEZpbmRNYXJrZXJzKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGlkZW50LjEgPSBjKCI0IiwgIjUiLCAiMTYiLCAiMTEiLCAiNyIsICIzIiwgIjkiLCAiMCIsICIyMiIpKQojaGVhZChtYXJrZXJzX3JpbmcpCgojIFBCQU5LQS0xMzE5NTAwIC0gQ0NQMiAtIGZlbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMDQxNjEwMCAtIE1HMSAtIGR5bmVuaW4gaGVhdnkgY2hhaW4gLSBtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0xNDM3NTAwIC0gQVAyRyAtIGNvbW1pdG1lbnQKIyBQQkFOS0EtMDgzMTAwMCAtIE1TUDEgLSBsYXRlIGFzZXh1YWwKIyBQQkFOS0EtMTEwMjIwMCAtIE1TUDggLSBlYXJseSBhc2V4dWFsIChmcm9tIEJvemRlY2ggcGFwZXIpCiMgUEJBTktBLTA3MTE5MDAgLSBIU1A3MCAtIHByb21vdGVyIHVzZWQgZm9yIEdGUCBhbmQgUkZQIGV4cHJlc3Npb24gaW4gdGhlIG11dGFudHMKIyBQQkFOS0EtMTQwMDQwMCAtIEZBTUIgLSByaW5nIG1hcmtlciAtIGRpc2NvdmVyZWQgYnkgbG9va2luZyBmb3IgbWFya2VyIGdlbmVzIGluIGRhdGEKIyBQQkFOS0EtMDcyMjYwMCAtIEZhbS1iMiAtIHJpbmcgbWFya2VyIC0gaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNTExMzAzMS8gCgoKbWFya2VyX2dlbmVfcGxvdF9DQ1AyIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xMzE5NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhjY3AyKSwgIihGZW1hbGUpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCm1hcmtlcl9nZW5lX3Bsb3RfTUcxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNDE2MTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMobWcxKSwgIihNYWxlKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X0FQMkcgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTE0Mzc1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKGFwMmcpLCAiKENvbW1pdG1lbnQpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCm1hcmtlcl9nZW5lX3Bsb3RfTVNQMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDgzMTAwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMobXNwMSksICIoU2NoaXpvbnQpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCm1hcmtlcl9nZW5lX3Bsb3RfTVNQOCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMjIwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMobXNwOCksICIoQXNleHVhbCkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9TQlAxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xMTAxMzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhzYnAxKSwgIihSaW5nKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X0ZBTUIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA3MjI2MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKGZhbS1iMiksICAiKFJpbmcpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCm1hcmtlcl9nZW5lX3Bsb3RfSFNQNzAgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA3MTE5MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMoSFNQNzApLCAgIihSZXBvcnRlcikiLCJcbiIsICJQQkFOS0FfMDcxMTkwMCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgojI29yaWdpbmFsIGxhYmVsOgojIGxhYnModGl0bGUgPSBwYXN0ZSgiKENDUDI7IEZlbWFsZSkiLCJcbiIsICJQQkFOS0FfMTMxOTUwMCIpKQoKIyMgcGxvdAojIyBjb3dwbG90IG1ldGhvZAptYXJrZXJfZ2VuZV9wbG90X2FsbCA8LSBwbG90X2dyaWQobWFya2VyX2dlbmVfcGxvdF9GQU1CLCBtYXJrZXJfZ2VuZV9wbG90X01TUDgsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQMSwgbWFya2VyX2dlbmVfcGxvdF9BUDJHLCBtYXJrZXJfZ2VuZV9wbG90X0NDUDIsIG1hcmtlcl9nZW5lX3Bsb3RfTUcxLCBtYXJrZXJfZ2VuZV9wbG90X0hTUDcwLCBucm93PTMpCgptYXJrZXJfZ2VuZV9wbG90X2FsbAoKIyMgcGF0Y2h3b3JrIG1ldGhvZAojbWFya2VyX2dlbmVfcGxvdF9GQU1CICsgbWFya2VyX2dlbmVfcGxvdF9NU1A4ICsgbWFya2VyX2dlbmVfcGxvdF9NU1AxICsgbWFya2VyX2dlbmVfcGxvdF9BUDJHICsgbWFya2VyX2dlbmVfcGxvdF9DQ1AyICsgbWFya2VyX2dlbmVfcGxvdF9NRzEgKyBtYXJrZXJfZ2VuZV9wbG90X0hTUDcwCmBgYAoKIyMjIyBFeHByZXNzaW9uIC0gcmF3IC0gcHVycGxlCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTUsIGZpZy53aWR0aCA9IDE1fQoKbWFya2VyX2dlbmVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIiNEM0QzRDMiLCAiIzFEMTU2NCIpKSg1MCkKCm1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTMxOTUwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiQ0NQMiAoRmVtYWxlKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9NRzEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTYxMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJNRzEgKE1hbGUpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgptYXJrZXJfZ2VuZV9wbG90X0FQMkcgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTE0Mzc1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIkFQMkcgKENvbW1pdG1lbnQpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgptYXJrZXJfZ2VuZV9wbG90X01TUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA4MzEwMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIk1TUDEgKFNjaGl6b250KSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9NU1A4IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xMTAyMjAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJNU1A4IChBc2V4dWFsKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9TQlAxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xMTAxMzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTQlAxIChSaW5nKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9GQU1CIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzIyNjAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJGYW0tYjIgKFJpbmcpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgptYXJrZXJfZ2VuZV9wbG90X0hTUDcwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzExOTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIihIU1A3MDsgUmVwb3J0ZXIpIiwiXG4iLCAiUEJBTktBXzA3MTE5MDAiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCiMjIHBsb3QKIyMgY293cGxvdCBtZXRob2QKbWFya2VyX2dlbmVfcGxvdF9hbGwgPC0gcGxvdF9ncmlkKG1hcmtlcl9nZW5lX3Bsb3RfRkFNQiwgbWFya2VyX2dlbmVfcGxvdF9NU1A4LCBtYXJrZXJfZ2VuZV9wbG90X01TUDEsIG1hcmtlcl9nZW5lX3Bsb3RfQVAyRywgbWFya2VyX2dlbmVfcGxvdF9DQ1AyLCBtYXJrZXJfZ2VuZV9wbG90X01HMSwgbWFya2VyX2dlbmVfcGxvdF9IU1A3MCwgbnJvdz0zKQoKbWFya2VyX2dlbmVfcGxvdF9hbGwKYGBgCgojIyMjIEV4cHJlc3Npb24gLSBkYXRhIC0gcHVycGxlCgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyBQQkFOS0EtMTQxODEwMCAgICAgICAgR0NTS08tMTcgIEZEMyAgIAojIFBCQU5LQS0wMTAyNDAwICAgICAgICAgR0NTS08tMiAgTUQzIAojIFBCQU5LQS0wNzE2NTAwICAgICAgICBHQ1NLTy0xOSAgTUQ0IAojIFBCQU5LQS0xNDM1MjAwICAgICAgICBHQ1NLTy0yMCAgRkQ0IAojIFBCQU5LQS0wOTAyMzAwICAgICAgICBHQ1NLTy0xMyAgRkQyCiMgUEJBTktBLTA0MTM0MDAgICAgR0NTS08tMTBfODIwICBNRDUKIyBQQkFOS0EtMDgyODAwMCAgICAgICAgIEdDU0tPLTMgIEdEMQojIFBCQU5LQS0xMzAyNzAwICAgICAgIEdDU0tPLW9vbSAgTUQxIAojIFBCQU5LQS0xNDQ3OTAwICAgICAgICBHQ1NLTy0yOSAgTUQyCiMgUEJBTktBLTE0NTQ4MDAgICAgICAgIEdDU0tPLTIxICBGRDEKIyBQQkFOS0EtMTE0NDgwMCAgICAgICAgR0NTS08tMjggIEZENQoKCm1hcmtlcl9nZW5lX3Bsb3RfMTcgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQxODEwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDMiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8yIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTAxMDI0MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQzIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMTkgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDcxNjUwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8yMCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM1MjAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkNCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzEzIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA5MDIzMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQyIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMTAgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDQxMzQwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDUiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8zIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA4MjgwMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZ2QxIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3Rfb29tIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTEzMDI3MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQxIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjkgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ0NzkwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDIiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8yMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDU0ODAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgojI29yaWdpbmFsIGxhYmVsOgojIGxhYnModGl0bGUgPSBwYXN0ZSgiKENDUDI7IEZlbWFsZSkiLCJcbiIsICJQQkFOS0FfMTMxOTUwMCIpKQoKIyMgbWFrZSBjb21wb3NpdGUgcGxvdAptdXRhbnRfZXhwcmVzc2lvbl9jb21wb3NpdGUgPC0gd3JhcF9wbG90cyhtYXJrZXJfZ2VuZV9wbG90XzE3ICwgbWFya2VyX2dlbmVfcGxvdF8yICwgbWFya2VyX2dlbmVfcGxvdF8xOSAsIG1hcmtlcl9nZW5lX3Bsb3RfMjAgLCBtYXJrZXJfZ2VuZV9wbG90XzEzICwgbWFya2VyX2dlbmVfcGxvdF8xMCAsIG1hcmtlcl9nZW5lX3Bsb3RfMyAsIG1hcmtlcl9nZW5lX3Bsb3Rfb29tICwgbWFya2VyX2dlbmVfcGxvdF8yOSAsIG1hcmtlcl9nZW5lX3Bsb3RfMjEgLCBuY29sID0gNCkKICAgICAgICAgICAKIyMgcHJpbnQKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlCmBgYAoKIyBEZW5zaXR5IFBsb3RzCgojIyMjIERlbnNpdHkgLSBwdXJwbGUKCmBgYHtyfQojIFBCQU5LQS0xMzE5NTAwIC0gQ0NQMiAtIGZlbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMDQxNjEwMCAtIE1HMSAtIGR5bmVuaW4gaGVhdnkgY2hhaW4gLSBtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0xNDM3NTAwIC0gQVAyRyAtIGNvbW1pdG1lbnQKIyBQQkFOS0EtMDgzMTAwMCAtIE1TUDEgLSBsYXRlIGFzZXh1YWwKIyBQQkFOS0EtMTEwMjIwMCAtIE1TUDggLSBlYXJseSBhc2V4dWFsIChmcm9tIEJvemRlY2ggcGFwZXIpCiMgUEJBTktBLTA3MTE5MDAgLSBIU1A3MCAtIHByb21vdGVyIHVzZWQgZm9yIEdGUCBhbmQgUkZQIGV4cHJlc3Npb24gaW4gdGhlIG11dGFudHMKIyBQQkFOS0EtMTQwMDQwMCAtIEZBTUIgLSByaW5nIG1hcmtlciAtIGRpc2NvdmVyZWQgYnkgbG9va2luZyBmb3IgbWFya2VyIGdlbmVzIGluIGRhdGEKIyBQQkFOS0EtMDcyMjYwMCAtIEZhbS1iMiAtIHJpbmcgbWFya2VyIC0gaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNTExMzAzMS8gCgptYXJrZXJzX2xpc3QgPC0gYygiUEJBTktBLTA4MjgwMDAiLCAiUEJBTktBLTEzMDI3MDAiLCAiUEJBTktBLTE0NDc5MDAiLCAiUEJBTktBLTAxMDI0MDAiLCAiUEJBTktBLTA3MTY1MDAiLCAiUEJBTktBLTA0MTM0MDAiLCAiUEJBTktBLTE0NTQ4MDAiLCAiUEJBTktBLTA5MDIzMDAiLCAiUEJBTktBLTE0MTgxMDAiLCAiUEJBTktBLTE0MzUyMDAiKQoKbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lcyA8LSBwbG90X2RlbnNpdHkodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbWFya2Vyc19saXN0LCBqb2ludCA9IEZBTFNFLCBjb21iaW5lID0gRkFMU0UsIGRpbXMgPSBjKDEsMiksIHBhbCA9ICJwbGFzbWEiLCBtZXRob2QgPSAia3MiKQoKIyMgbWFrZSBjb21wb3NpdGUgcGxvdApVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMgPC0gd3JhcF9wbG90cyhsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJnZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMl1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbM11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzRdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMyIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s1XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDQiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNl1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzddXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMSIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s4XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzEwXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDQiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDQpCgpVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMKYGBgCgoKIyMjIyBEZW5zaXR5IC12aXJpZGlzCgpgYGB7cn0KIyBQQkFOS0EtMTMxOTUwMCAtIENDUDIgLSBmZW1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTA0MTYxMDAgLSBNRzEgLSBkeW5lbmluIGhlYXZ5IGNoYWluIC0gbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMTQzNzUwMCAtIEFQMkcgLSBjb21taXRtZW50CiMgUEJBTktBLTA4MzEwMDAgLSBNU1AxIC0gbGF0ZSBhc2V4dWFsCiMgUEJBTktBLTExMDIyMDAgLSBNU1A4IC0gZWFybHkgYXNleHVhbCAoZnJvbSBCb3pkZWNoIHBhcGVyKQojIFBCQU5LQS0wNzExOTAwIC0gSFNQNzAgLSBwcm9tb3RlciB1c2VkIGZvciBHRlAgYW5kIFJGUCBleHByZXNzaW9uIGluIHRoZSBtdXRhbnRzCiMgUEJBTktBLTE0MDA0MDAgLSBGQU1CIC0gcmluZyBtYXJrZXIgLSBkaXNjb3ZlcmVkIGJ5IGxvb2tpbmcgZm9yIG1hcmtlciBnZW5lcyBpbiBkYXRhCiMgUEJBTktBLTA3MjI2MDAgLSBGYW0tYjIgLSByaW5nIG1hcmtlciAtIGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzUxMTMwMzEvIAoKbWFya2Vyc19saXN0IDwtIGMoIlBCQU5LQS0wODI4MDAwIiwgIlBCQU5LQS0xMzAyNzAwIiwgIlBCQU5LQS0xNDQ3OTAwIiwgIlBCQU5LQS0wMTAyNDAwIiwgIlBCQU5LQS0wNzE2NTAwIiwgIlBCQU5LQS0wNDEzNDAwIiwgIlBCQU5LQS0xNDU0ODAwIiwgIlBCQU5LQS0wOTAyMzAwIiwgIlBCQU5LQS0xNDE4MTAwIiwgIlBCQU5LQS0xNDM1MjAwIikKCmxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXMgPC0gcGxvdF9kZW5zaXR5KHRlbnguanVzdHd0LmludGVncmF0ZWQsIG1hcmtlcnNfbGlzdCwgam9pbnQgPSBGQUxTRSwgY29tYmluZSA9IEZBTFNFLCBkaW1zID0gYygxLDIpLCBwYWwgPSAicGxhc21hIiwgbWV0aG9kID0gImtzIikKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzIDwtIHdyYXBfcGxvdHMobGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMV1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiZ2QxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMl1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1szXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDIiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s0XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpICkrIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s1XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDQiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s2XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDUiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s3XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s4XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s5XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxMF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDQpCgpVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMKYGBgCgojIyMjIERlbnNpdHkgLSB2aXJpZGlzCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIFBCQU5LQS0wODI4MDAwICAgICAgICAgR0NTS08tMyAgR0QxCgojIFBCQU5LQS0xMzAyNzAwICAgICAgIEdDU0tPLW9vbSAgTUQxIAojIFBCQU5LQS0xNDQ3OTAwICAgICAgICBHQ1NLTy0yOSAgTUQyCiMgUEJBTktBLTAxMDI0MDAgICAgICAgICBHQ1NLTy0yICBNRDMgCiMgUEJBTktBLTA3MTY1MDAgICAgICAgIEdDU0tPLTE5ICBNRDQgCiMgUEJBTktBLTA0MTM0MDAgICAgR0NTS08tMTBfODIwICBNRDUKCiMgUEJBTktBLTE0NTQ4MDAgICAgICAgIEdDU0tPLTIxICBGRDEKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0xNDE4MTAwICAgICAgICBHQ1NLTy0xNyAgRkQzICAgCiMgUEJBTktBLTE0MzUyMDAgICAgICAgIEdDU0tPLTIwICBGRDQgCgptYXJrZXJzX2xpc3QgPC0gYygiUEJBTktBLTA4MjgwMDAiLCAiUEJBTktBLTEzMDI3MDAiLCAiUEJBTktBLTE0NDc5MDAiLCAiUEJBTktBLTAxMDI0MDAiLCAiUEJBTktBLTA3MTY1MDAiLCAiUEJBTktBLTA0MTM0MDAiLCAiUEJBTktBLTE0NTQ4MDAiLCAiUEJBTktBLTA5MDIzMDAiLCAiUEJBTktBLTE0MTgxMDAiLCAiUEJBTktBLTE0MzUyMDAiKQoKbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lcyA8LSBwbG90X2RlbnNpdHkodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbWFya2Vyc19saXN0LCBqb2ludCA9IEZBTFNFLCBjb21iaW5lID0gRkFMU0UsIGRpbXMgPSBjKDEsMiksIHBhbCA9ICJwbGFzbWEiLCBtZXRob2QgPSAia3MiKQoKIyMgbWFrZSBjb21wb3NpdGUgcGxvdApVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMgPC0gd3JhcF9wbG90cyhsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJnZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1syXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgibWQxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzNdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMiIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzRdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMyIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkgKSsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzVdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNCIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzZdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNSIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzddXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMSIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzhdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMiIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzldXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMyIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzEwXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDQiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gNCkKClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcwoKIyMgSUYgcHV0dGluZyBpbiBNQUlOIC0gbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMl1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9OSkpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDQuMCwgdGl0bGUgPSAiIikpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKCiMgUEJBTktBLTEzMDI3MDAgICAgICAgR0NTS08tb29tICBNRDEgCiMgUEJBTktBLTE0NDc5MDAgICAgICAgIEdDU0tPLTI5ICBNRDIKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1EMyAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENCAKIyBQQkFOS0EtMDQxMzQwMCAgICBHQ1NLTy0xMF84MjAgIE1ENQoKIyBQQkFOS0EtMTQ1NDgwMCAgICAgICAgR0NTS08tMjEgIEZEMQojIFBCQU5LQS0wOTAyMzAwICAgICAgICBHQ1NLTy0xMyAgRkQyCiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKCm1hcmtlcnNfbGlzdCA8LSBjKCJQQkFOS0EtMDgyODAwMCIsICJQQkFOS0EtMTMwMjcwMCIsICJQQkFOS0EtMTQ0NzkwMCIsICJQQkFOS0EtMDEwMjQwMCIsICJQQkFOS0EtMDcxNjUwMCIsICJQQkFOS0EtMDQxMzQwMCIsICJQQkFOS0EtMTQ1NDgwMCIsICJQQkFOS0EtMDkwMjMwMCIsICJQQkFOS0EtMTQxODEwMCIsICJQQkFOS0EtMTQzNTIwMCIpCgpsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzIDwtIHBsb3RfZGVuc2l0eSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBtYXJrZXJzX2xpc3QsIGpvaW50ID0gRkFMU0UsIGNvbWJpbmUgPSBGQUxTRSwgZGltcyA9IGMoMSwyKSwgcGFsID0gInBsYXNtYSIsIG1ldGhvZCA9ICJ3a2RlIiwgc2xvdCA9ICdkYXRhJykKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzIDwtIHdyYXBfcGxvdHMobGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMV1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiZ2QxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMl1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1szXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDIiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzRdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMyIpKSArIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzVdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNCIpKSArIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzZdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNSIpKSArIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzddXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMSIpKSArIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzhdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMiIpKSArIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzldXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMyIpKSArIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzEwXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDQiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gNCkKCiMjIG9sZCBjb2xvdXIgc2NhbGU6IHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wICkKClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcwpgYGAKCgoKCgo=